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

