MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Evgeny Potemkin Date:August 28 2008 11:47am
Subject:bzr commit into mysql-5.0 branch (epotemkin:2679) Bug#37908
View as plain text  
#At file:///work/bzr_trees/37908-bug-5.0-bugteam/

 2679 Evgeny Potemkin	2008-08-28
      Bug#37908: Skipped access right check caused server crash.
            
      The check_table_access function initializes per-table grant info and performs
      access rights check. It wasn't called for SHOW STATUS statement thus left
      grants info uninitialized. In some cases this led to server crash. In other
      cases it allowed a user to check for presence/absence of arbitrary values in
      any tables.
            
      Now the check_table_access function is called prior to the statement
      processing.
      The check_table_access function is adjusted to correctly check access to
      system tables for schema tables filling.
modified:
  mysql-test/r/status.result
  mysql-test/t/status.test
  sql/sql_parse.cc
  sql/sql_yacc.yy

per-file messages:
  mysql-test/r/status.result
    Added a test case for the bug#37908.
  mysql-test/t/status.test
    Added a test case for the bug#37908.
  sql/sql_parse.cc
    Bug#37908: Skipped access right check caused server crash.
    Now the check_table_access function is called prior to the statement
    processing.
    The check_table_access function is adjusted to correctly check access to
    system tables for schema tables filling.
  sql/sql_yacc.yy
    Bug#37908: Skipped access right check caused server crash.
    The 'proc' table now is added to the tables list after access rights check.
=== modified file 'mysql-test/r/status.result'
--- a/mysql-test/r/status.result	2007-08-28 15:51:03 +0000
+++ b/mysql-test/r/status.result	2008-08-28 11:47:39 +0000
@@ -91,3 +91,21 @@ SHOW SESSION STATUS LIKE 'Last_query_cos
 Variable_name	Value
 Last_query_cost	4.805836
 DROP TABLE t1;
+create database db37908;
+create table db37908.t1(f1 int);
+insert into db37908.t1 values(1);
+grant usage,execute on test.* to mysqltest_1@localhost;
+create procedure proc37908() begin select 1; end |
+create function func37908() returns int sql security invoker 
+return (select * from db37908.t1 limit 1)|
+select * from db37908.t1;
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1'
+show status where variable_name ='uptime' and 2 in (select * from db37908.t1);
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1'
+show procedure status where name ='proc37908' and 1 in (select f1 from db37908.t1);
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1'
+show function status where name ='func37908' and 1 in (select func37908());
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1'
+drop database db37908;
+drop procedure proc37908;
+drop function func37908;

=== modified file 'mysql-test/t/status.test'
--- a/mysql-test/t/status.test	2007-08-28 15:51:03 +0000
+++ b/mysql-test/t/status.test	2008-08-28 11:47:39 +0000
@@ -171,4 +171,37 @@ SHOW SESSION STATUS LIKE 'Last_query_cos
 DROP TABLE t1;
 
 
+#
+# Bug#37908: Skipped access right check caused server crash.
+#
+connect (root, localhost, root,,test);
+connection root;
+--disable_warnings
+create database db37908;
+--enable_warnings
+create table db37908.t1(f1 int);
+insert into db37908.t1 values(1);
+grant usage,execute on test.* to mysqltest_1@localhost;
+delimiter |;
+create procedure proc37908() begin select 1; end |
+create function func37908() returns int sql security invoker 
+  return (select * from db37908.t1 limit 1)|
+delimiter ;|
+  
+connect (user1,localhost,mysqltest_1,,test);
+connection user1;
+
+--error 1142
+select * from db37908.t1;
+--error 1142
+show status where variable_name ='uptime' and 2 in (select * from db37908.t1);
+--error 1142
+show procedure status where name ='proc37908' and 1 in (select f1 from db37908.t1);
+--error 1142
+show function status where name ='func37908' and 1 in (select func37908());
+
+connection root;
+drop database db37908;
+drop procedure proc37908;
+drop function func37908;
 # End of 5.0 tests

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2008-08-26 08:32:43 +0000
+++ b/sql/sql_parse.cc	2008-08-28 11:47:39 +0000
@@ -2670,12 +2670,14 @@ mysql_execute_command(THD *thd)
     select_result *sel_result=lex->result;
     if (all_tables)
     {
-      if (lex->orig_sql_command != SQLCOM_SHOW_STATUS_PROC &&
-          lex->orig_sql_command != SQLCOM_SHOW_STATUS_FUNC)
         res= check_table_access(thd,
                                 lex->exchange ? SELECT_ACL | FILE_ACL :
                                 SELECT_ACL,
                                 all_tables, 0);
+      if (!res &&
+          (lex->orig_sql_command == SQLCOM_SHOW_STATUS_PROC ||
+          lex->orig_sql_command == SQLCOM_SHOW_STATUS_FUNC))
+        res= !sp_add_to_query_tables(thd, thd->lex, "mysql", "proc", TL_READ);
     }
     else
       res= check_access(thd,
@@ -5609,6 +5611,7 @@ check_table_access(THD *thd, ulong want_
 		   bool no_errors)
 {
   uint found=0;
+  uint number= 0;
   ulong found_access=0;
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
   TABLE_LIST *org_tables= tables;
@@ -5620,8 +5623,9 @@ check_table_access(THD *thd, ulong want_
     the given table list refers to the list for prelocking (contains tables
     of other queries). For simple queries first_not_own_table is 0.
   */
-  for (; tables != first_not_own_table; tables= tables->next_global)
+  for (; tables != first_not_own_table && tables; tables= tables->next_global)
   {
+    number++;
     if (tables->security_ctx)
       sctx= tables->security_ctx;
     else
@@ -5680,7 +5684,8 @@ check_table_access(THD *thd, ulong want_
   thd->security_ctx= backup_ctx;
   if (grant_option)
     return check_grant(thd,want_access & ~EXTRA_ACL,org_tables,
-		       test(want_access & EXTRA_ACL), UINT_MAX, no_errors);
+		       test(want_access & EXTRA_ACL),
+                       (number ? number : UINT_MAX), no_errors);
   return FALSE;
 deny:
   thd->security_ctx= backup_ctx;

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2008-08-11 16:10:00 +0000
+++ b/sql/sql_yacc.yy	2008-08-28 11:47:39 +0000
@@ -8177,8 +8177,6 @@ show_param:
             LEX *lex= Lex;
             lex->sql_command= SQLCOM_SELECT;
             lex->orig_sql_command= SQLCOM_SHOW_STATUS_PROC;
-	    if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ))
-	      MYSQL_YYABORT;
             if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
               MYSQL_YYABORT;
 	  }
@@ -8187,8 +8185,6 @@ show_param:
             LEX *lex= Lex;
             lex->sql_command= SQLCOM_SELECT;
             lex->orig_sql_command= SQLCOM_SHOW_STATUS_FUNC;
-	    if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ))
-	      MYSQL_YYABORT;
             if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
               MYSQL_YYABORT;
 	  }

Thread
bzr commit into mysql-5.0 branch (epotemkin:2679) Bug#37908Evgeny Potemkin28 Aug