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;
       }
     }

Attachment: signature.asc
Description: Digital signature

Reply via email to