tags 285276 patch tags 296674 patch thanks hi,
i believe the attached patch fixes the vulnerability. i took the redhat src rpm patch "mysql-3.23.58-security.patch", removed the parts of the patch that are already addressed by other DSA's, adjusted some line numbers, and did a little extra massaging to get it to fit. the patch cleanly applies, the package builds and installs, mysql starts up, and i can connect to the database all without problems. however, this is all in my virgin woody-i386 chroot on an unstable amd64 box, and i haven't tested that the vulnerability is actually gone. could someone more familiar with the vulnerability try a before and after to see if the problem is resolved? sean --
diff -Naur mysql-3.23.58-orig/include/my_sys.h mysql-3.23.58/include/my_sys.h --- mysql-3.23.58-orig/include/my_sys.h 2003-09-11 07:49:20.000000000 -0400 +++ mysql-3.23.58/include/my_sys.h 2004-10-12 13:27:15.380784008 -0400 @@ -476,7 +476,7 @@ const char *own_pathname_part); extern my_string my_load_path(my_string to, const char *path, const char *own_path_prefix); -extern int wild_compare(const char *str,const char *wildstr); +extern int wild_compare(const char *str,const char *wildstr,pbool str_is_pattern); extern my_string my_strcasestr(const char *src,const char *suffix); extern int my_strcasecmp(const char *s,const char *t); extern int my_strsortcmp(const char *s,const char *t); diff -Naur mysql-3.23.58-orig/mysys/mf_wcomp.c mysql-3.23.58/mysys/mf_wcomp.c --- mysql-3.23.58-orig/mysys/mf_wcomp.c 2003-09-11 07:49:19.000000000 -0400 +++ mysql-3.23.58/mysys/mf_wcomp.c 2004-10-12 13:27:15.382783734 -0400 @@ -24,11 +24,12 @@ char wild_many='*'; char wild_one='?'; -char wild_prefix=0; +char wild_prefix=0; /* QQ this can potentially cause a SIGSEGV */ -int wild_compare(register const char *str, register const char *wildstr) +int wild_compare(register const char *str, register const char *wildstr, + pbool str_is_pattern) { - reg3 int flag; + char cmp; DBUG_ENTER("wild_compare"); while (*wildstr) @@ -36,33 +37,55 @@ while (*wildstr && *wildstr != wild_many && *wildstr != wild_one) { if (*wildstr == wild_prefix && wildstr[1]) + { wildstr++; - if (*wildstr++ != *str++) DBUG_RETURN(1); + if (str_is_pattern && *str++ != wild_prefix) + DBUG_RETURN(1); + } + if (*wildstr++ != *str++) + DBUG_RETURN(1); } - if (! *wildstr ) DBUG_RETURN (*str != 0); + if (! *wildstr ) + DBUG_RETURN(*str != 0); if (*wildstr++ == wild_one) { - if (! *str++) DBUG_RETURN (1); /* One char; skipp */ + if (! *str || (str_is_pattern && *str == wild_many)) + DBUG_RETURN(1); /* One char; skip */ + if (*str++ == wild_prefix && str_is_pattern && *str) + str++; } else { /* Found '*' */ - if (!*wildstr) DBUG_RETURN(0); /* '*' as last char: OK */ - flag=(*wildstr != wild_many && *wildstr != wild_one); - do + while (str_is_pattern && *str == wild_many) + str++; + for (; *wildstr == wild_many || *wildstr == wild_one; wildstr++) + if (*wildstr == wild_many) + { + while (str_is_pattern && *str == wild_many) + str++; + } + else + { + if (str_is_pattern && *str == wild_prefix && str[1]) + str+=2; + else if (! *str++) + DBUG_RETURN (1); + } + if (!*wildstr) + DBUG_RETURN(0); /* '*' as last char: OK */ + if ((cmp= *wildstr) == wild_prefix && wildstr[1] && !str_is_pattern) + cmp=wildstr[1]; + for (;;str++) { - if (flag) - { - char cmp; - if ((cmp= *wildstr) == wild_prefix && wildstr[1]) - cmp=wildstr[1]; - while (*str && *str != cmp) - str++; - if (!*str) DBUG_RETURN (1); - } - if (wild_compare(str,wildstr) == 0) DBUG_RETURN (0); - } while (*str++ && wildstr[0] != wild_many); - DBUG_RETURN(1); + while (*str && *str != cmp) + str++; + if (!*str) + DBUG_RETURN (1); + if (wild_compare(str,wildstr,str_is_pattern) == 0) + DBUG_RETURN (0); + } + /* We will never come here */ } } - DBUG_RETURN (*str != '\0'); + DBUG_RETURN (*str != 0); } /* wild_compare */ diff -Naur mysql-3.23.58-orig/mysys/mf_wfile.c mysql-3.23.58/mysys/mf_wfile.c --- mysql-3.23.58-orig/mysys/mf_wfile.c 2003-09-11 07:49:20.000000000 -0400 +++ mysql-3.23.58/mysys/mf_wfile.c 2004-10-12 13:27:15.383783596 -0400 @@ -107,7 +107,7 @@ not_pos=wf_pack->not_pos; for (i=0 ; i < not_pos; i++) - if (wild_compare(name,wf_pack->wild[i]) == 0) + if (wild_compare(name,wf_pack->wild[i],0) == 0) goto found; if (i) DBUG_RETURN(1); /* No-match */ @@ -116,7 +116,7 @@ /* Test that it isn't in not-list */ for (i=not_pos ; i < wf_pack->wilds; i++) - if (wild_compare(name,wf_pack->wild[i]) == 0) + if (wild_compare(name,wf_pack->wild[i],0) == 0) DBUG_RETURN(1); DBUG_RETURN(0); } /* wf_test */ diff -Naur mysql-3.23.58-orig/sql/sql_acl.cc mysql-3.23.58/sql/sql_acl.cc --- mysql-3.23.58-orig/sql/sql_acl.cc 2003-09-11 07:49:20.000000000 -0400 +++ mysql-3.23.58/sql/sql_acl.cc 2004-10-12 13:31:59.347857356 -0400 @@ -566,7 +566,7 @@ *****************************************************************************/ uint acl_get(const char *host, const char *ip, const char *bin_ip, - const char *user, const char *db) + const char *user, const char *db, my_bool db_is_pattern) { uint host_access,db_access,i,key_length; db_access=0; host_access= ~0; @@ -594,7 +594,7 @@ { if (compare_hostname(&acl_db->host,host,ip)) { - if (!acl_db->db || !wild_compare(db,acl_db->db)) + if (!acl_db->db || !wild_compare(db,acl_db->db,db_is_pattern)) { db_access=acl_db->access; if (acl_db->host.hostname) @@ -616,7 +616,7 @@ ACL_HOST *acl_host=dynamic_element(&acl_hosts,i,ACL_HOST*); if (compare_hostname(&acl_host->host,host,ip)) { - if (!acl_host->db || !wild_compare(db,acl_host->db)) + if (!acl_host->db || !wild_compare(db,acl_host->db,0)) { host_access=acl_host->access; // Fully specified. Take it break; @@ -897,7 +897,7 @@ } return (!host->hostname || (hostname && !wild_case_compare(hostname,host->hostname)) || - (ip && !wild_compare(ip,host->hostname))); + (ip && !wild_compare(ip,host->hostname,0))); } @@ -957,7 +957,7 @@ tl.db= (char*) "mysql"; tl.real_name= (char*) "user"; db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, - thd->priv_user, tl.db); + thd->priv_user, tl.db, 0); if (!(db_access & INSERT_ACL)) { if (check_grant(thd,INSERT_ACL,&tl,0,1)) diff -Naur mysql-3.23.58-orig/sql/sql_acl.h mysql-3.23.58/sql/sql_acl.h --- mysql-3.23.58-orig/sql/sql_acl.h 2003-09-11 07:49:21.000000000 -0400 +++ mysql-3.23.58/sql/sql_acl.h 2004-10-12 13:31:22.514906647 -0400 @@ -58,7 +58,7 @@ void acl_reload(void); void acl_free(bool end=0); uint acl_get(const char *host, const char *ip, const char *bin_ip, - const char *user, const char *db); + const char *user, const char *db, my_bool db_is_pattern); uint acl_getroot(const char *host, const char *ip, const char *user, const char *password,const char *scramble,char **priv_user, bool old_ver); diff -Naur mysql-3.23.58-orig/sql/sql_base.cc mysql-3.23.58/sql/sql_base.cc --- mysql-3.23.58-orig/sql/sql_base.cc 2003-09-11 07:49:19.000000000 -0400 +++ mysql-3.23.58/sql/sql_base.cc 2004-10-12 13:30:32.114815731 -0400 @@ -126,7 +126,7 @@ TABLE *entry=(TABLE*) hash_element(&open_cache,idx); if ((!entry->real_name) || strcmp(entry->table_cache_key,db)) continue; - if (wild && wild[0] && wild_compare(entry->real_name,wild)) + if (wild && wild[0] && wild_compare(entry->real_name,wild,0)) continue; if (db && !(col_access & TABLE_ACLS)) { diff -Naur mysql-3.23.58-orig/sql/sql_db.cc mysql-3.23.58/sql/sql_db.cc --- mysql-3.23.58-orig/sql/sql_db.cc 2003-09-11 07:49:20.000000000 -0400 +++ mysql-3.23.58/sql/sql_db.cc 2004-10-12 13:27:15.396781815 -0400 @@ -329,7 +329,7 @@ db_access=DB_ACLS; else db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr, - thd->priv_user,dbname) | + thd->priv_user,dbname,0) | thd->master_access); if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) { diff -Naur mysql-3.23.58-orig/sql/sql_parse.cc mysql-3.23.58/sql/sql_parse.cc --- mysql-3.23.58-orig/sql/sql_parse.cc 2003-09-11 07:49:19.000000000 -0400 +++ mysql-3.23.58/sql/sql_parse.cc 2004-10-12 13:27:15.401781129 -0400 @@ -2138,7 +2138,7 @@ if (db && (!thd->db || strcmp(db,thd->db))) db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, - thd->priv_user, db); /* purecov: inspected */ + thd->priv_user, db, 0); /* purecov: inspected */ else db_access=thd->db_access; want_access &= ~EXTRA_ACL; // Remove SHOW attribute diff -Naur mysql-3.23.58-orig/sql/sql_show.cc mysql-3.23.58/sql/sql_show.cc --- mysql-3.23.58-orig/sql/sql_show.cc 2003-09-11 07:49:21.000000000 -0400 +++ mysql-3.23.58/sql/sql_show.cc 2004-10-12 13:32:33.561167139 -0400 @@ -77,7 +77,7 @@ { if (!opt_safe_show_db || thd->master_access || acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, - thd->priv_user, file_name) || + thd->priv_user, file_name, 0) || (grant_option && !check_grant_db(thd, file_name))) { thd->packet.length(0); @@ -202,7 +202,7 @@ #endif { if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat.st_mode) || - (wild && wild_compare(file->name,wild))) + (wild && wild_compare(file->name,wild,0))) continue; } } @@ -220,7 +220,7 @@ if (wild_case_compare(file->name,wild)) continue; } - else if (wild_compare(file->name,wild)) + else if (wild_compare(file->name,wild, 0)) continue; } }
signature.asc
Description: Digital signature