MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:kgeorge Date:September 22 2007 1:19pm
Subject:bk commit into 5.0 tree (gkodinov:1.2511) BUG#30468
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of kgeorge. When kgeorge does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-09-22 16:19:01+03:00, gkodinov@stripped +6 -0
  Bug #30468: column level privileges not respected when joining tables
  
  When expanding a * in a USING/NATURAL join the check for table access
  for both tables in the join was done using the grant information of the
  first one.
  Fixed by getting the grant information for the current table while 
  iterating through the columns of the join.

  mysql-test/r/grant2.result@stripped, 2007-09-22 16:19:00+03:00, gkodinov@stripped +18 -0
    Bug #30468: test case

  mysql-test/t/grant2.test@stripped, 2007-09-22 16:19:00+03:00, gkodinov@stripped +32 -0
    Bug #30468: test case

  sql/sql_acl.cc@stripped, 2007-09-22 16:19:00+03:00, gkodinov@stripped +68 -37
    Bug #30468: correctly check column grants

  sql/sql_acl.h@stripped, 2007-09-22 16:19:00+03:00, gkodinov@stripped +2 -3
    Bug #30468: correctly check column grants

  sql/sql_base.cc@stripped, 2007-09-22 16:19:00+03:00, gkodinov@stripped +1 -4
    Bug #30468: correctly check column grants

  sql/sql_insert.cc@stripped, 2007-09-22 16:19:00+03:00, gkodinov@stripped +3 -5
    Bug #30468: correctly check column grants

diff -Nrup a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result
--- a/mysql-test/r/grant2.result	2007-06-08 12:42:07 +03:00
+++ b/mysql-test/r/grant2.result	2007-09-22 16:19:00 +03:00
@@ -421,4 +421,22 @@ revoke all privileges, grant option from
 revoke all privileges, grant option from mysqltest_2@localhost;
 drop user mysqltest_1@localhost;
 drop user mysqltest_2@localhost;
+CREATE DATABASE db1;
+USE db1;
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,1),(2,2);
+CREATE TABLE t2 (b INT, c INT);
+INSERT INTO t2 VALUES (1,100),(2,200);
+GRANT SELECT ON t1 TO mysqltest1@localhost;
+GRANT SELECT (b) ON t2 TO mysqltest1@localhost;
+USE db1;
+SELECT c FROM t2;
+ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in table 't2'
+SELECT * FROM t2;
+ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in table 't2'
+SELECT * FROM t1 JOIN t2 USING (b);
+ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in table 't2'
+DROP TABLE db1.t1, db1.t2;
+DROP USER mysqltest1@localhost;
+DROP DATABASE db1;
 End of 5.0 tests
diff -Nrup a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test
--- a/mysql-test/t/grant2.test	2007-06-08 12:42:07 +03:00
+++ b/mysql-test/t/grant2.test	2007-09-22 16:19:00 +03:00
@@ -585,5 +585,37 @@ drop user mysqltest_1@localhost;
 drop user mysqltest_2@localhost;
 
 
+#
+# Bug #30468: column level privileges not respected when joining tables
+#
+CREATE DATABASE db1;
+
+USE db1;
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,1),(2,2);
+
+CREATE TABLE t2 (b INT, c INT);
+INSERT INTO t2 VALUES (1,100),(2,200);
+
+GRANT SELECT ON t1 TO mysqltest1@localhost; 
+GRANT SELECT (b) ON t2 TO mysqltest1@localhost;
+
+connect (conn1,localhost,mysqltest1,,);
+connection conn1;
+USE db1;
+--error ER_COLUMNACCESS_DENIED_ERROR
+SELECT c FROM t2;
+--error ER_COLUMNACCESS_DENIED_ERROR
+SELECT * FROM t2;
+--error ER_COLUMNACCESS_DENIED_ERROR
+SELECT * FROM t1 JOIN t2 USING (b);
+
+connection default;
+disconnect conn1;
+DROP TABLE db1.t1, db1.t2;
+DROP USER mysqltest1@localhost;
+DROP DATABASE db1;
+
+
 --echo End of 5.0 tests
 
diff -Nrup a/sql/sql_acl.cc b/sql/sql_acl.cc
--- a/sql/sql_acl.cc	2007-06-20 15:24:27 +03:00
+++ b/sql/sql_acl.cc	2007-09-22 16:19:00 +03:00
@@ -3835,50 +3835,81 @@ bool check_column_grant_in_table_ref(THD
 }
 
 
-bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
-                             const char* db_name, const char *table_name,
-                             Field_iterator *fields)
+/** 
+  @brief check if a query can access a set of columns
+
+  @param  thd  the current thread
+  @param  want_access_arg  the privileges requested
+  @param  fields an iterator over the fields of a table reference.
+  @return Operation status
+    @retval 0 Success
+    @retval 1 Falure
+  @details This function walks over the columns of a table reference 
+   The columns may originate from different tables, depending on the kind of
+   table reference, e.g. join.
+   For each table it will retrieve the grant information and will use it
+   to check the required access privileges for the fields requested from it.
+*/    
+bool check_grant_all_columns(THD *thd, ulong want_access_arg, 
+                             Field_iterator_table_ref *fields)
 {
   Security_context *sctx= thd->security_ctx;
-  GRANT_TABLE *grant_table;
-  GRANT_COLUMN *grant_column;
-
-  want_access &= ~grant->privilege;
-  if (!want_access)
-    return 0;				// Already checked
-  if (!grant_option)
-    goto err2;
-
-  rw_rdlock(&LOCK_grant);
-
-  /* reload table if someone has modified any grants */
+  ulong want_access= want_access_arg;
+  const char *table_name= NULL;
 
-  if (grant->version != grant_version)
+  if (grant_option)
   {
-    grant->grant_table=
-      table_hash_search(sctx->host, sctx->ip, db_name,
-			sctx->priv_user,
-			table_name, 0);	/* purecov: inspected */
-    grant->version= grant_version;		/* purecov: inspected */
-  }
-  /* The following should always be true */
-  if (!(grant_table= grant->grant_table))
-    goto err;					/* purecov: inspected */
+    const char* db_name; 
+    GRANT_INFO *grant;
+    GRANT_TABLE *grant_table;
+
+    rw_rdlock(&LOCK_grant);
+
+    for (; !fields->end_of_fields(); fields->next())
+    {
+      const char *field_name= fields->name();
+
+      if (table_name != fields->table_name())
+      {
+        table_name= fields->table_name();
+        db_name= fields->db_name();
+        grant= fields->grant();
+        /* get a fresh one for each table */
+        want_access= want_access_arg & ~grant->privilege;
+        if (want_access)
+        {
+          /* reload table if someone has modified any grants */
+          if (grant->version != grant_version)
+          {
+            grant->grant_table=
+              table_hash_search(sctx->host, sctx->ip, db_name,
+                                sctx->priv_user,
+                                table_name, 0);	/* purecov: inspected */
+            grant->version= grant_version;	/* purecov: inspected */
+          }
+
+          DBUG_ASSERT (!(grant_table= grant->grant_table));
+        }
+      }
+
+      if (want_access)
+      {
+        GRANT_COLUMN *grant_column= 
+          column_hash_search(grant_table, field_name,
+                             (uint) strlen(field_name));
+        if (!grant_column || (~grant_column->rights & want_access))
+          goto err;
+      }
+    }
+    rw_unlock(&LOCK_grant);
+    return 0;
 
-  for (; !fields->end_of_fields(); fields->next())
-  {
-    const char *field_name= fields->name();
-    grant_column= column_hash_search(grant_table, field_name,
-				    (uint) strlen(field_name));
-    if (!grant_column || (~grant_column->rights & want_access))
-      goto err;
+err:
+    rw_unlock(&LOCK_grant);
   }
-  rw_unlock(&LOCK_grant);
-  return 0;
+  else
+    table_name= fields->table_name();
 
-err:
-  rw_unlock(&LOCK_grant);
-err2:
   char command[128];
   get_privilege_desc(command, sizeof(command), want_access);
   my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
diff -Nrup a/sql/sql_acl.h b/sql/sql_acl.h
--- a/sql/sql_acl.h	2007-03-21 15:27:29 +02:00
+++ b/sql/sql_acl.h	2007-09-22 16:19:00 +03:00
@@ -205,9 +205,8 @@ bool check_grant_column (THD *thd, GRANT
 			 const char *name, uint length, Security_context *sctx);
 bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref,
                                      const char *name, uint length);
-bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
-                             const char* db_name, const char *table_name,
-                             Field_iterator *fields);
+bool check_grant_all_columns(THD *thd, ulong want_access, 
+                             Field_iterator_table_ref *fields);
 bool check_grant_routine(THD *thd, ulong want_access,
 			 TABLE_LIST *procs, bool is_proc, bool no_error);
 bool check_grant_db(THD *thd,const char *db);
diff -Nrup a/sql/sql_base.cc b/sql/sql_base.cc
--- a/sql/sql_base.cc	2007-08-23 22:28:27 +03:00
+++ b/sql/sql_base.cc	2007-09-22 16:19:00 +03:00
@@ -5414,10 +5414,7 @@ insert_fields(THD *thd, Name_resolution_
         !any_privileges)
     {
       field_iterator.set(tables);
-      if (check_grant_all_columns(thd, SELECT_ACL, field_iterator.grant(),
-                                  field_iterator.db_name(),
-                                  field_iterator.table_name(),
-                                  &field_iterator))
+      if (check_grant_all_columns(thd, SELECT_ACL, &field_iterator))
         DBUG_RETURN(TRUE);
     }
 #endif
diff -Nrup a/sql/sql_insert.cc b/sql/sql_insert.cc
--- a/sql/sql_insert.cc	2007-08-03 00:26:02 +03:00
+++ b/sql/sql_insert.cc	2007-09-22 16:19:00 +03:00
@@ -189,11 +189,9 @@ static int check_insert_fields(THD *thd,
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
     if (grant_option)
     {
-      Field_iterator_table field_it;
-      field_it.set_table(table);
-      if (check_grant_all_columns(thd, INSERT_ACL, &table->grant,
-                                  table->s->db, table->s->table_name,
-                                  &field_it))
+      Field_iterator_table_ref field_it;
+      field_it.set(table_list);
+      if (check_grant_all_columns(thd, INSERT_ACL, &field_it))
         return -1;
     }
 #endif
Thread
bk commit into 5.0 tree (gkodinov:1.2511) BUG#30468kgeorge22 Sep