From: Dmitry Lenev Date: December 1 2010 10:07am Subject: bzr commit into mysql-trunk-bugfixing branch (Dmitry.Lenev:3393) Bug#27480 List-Archive: http://lists.mysql.com/commits/125627 X-Bug: 27480 Message-Id: <20101201100740.339E91E520D@mockturtle> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0270261209==" --===============0270261209== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/dlenev/src/bzr/mysql-trunk-bugfixing-bug27480/ based on revid:dmitry.lenev@stripped 3393 Dmitry Lenev 2010-12-01 Prerequisite patch for Bug#27480 (Extend CREATE TEMPORARY TABLES privilege to allow temp table operations). Review fixes in progress. Fixed handling of administrative commands, extended test-coverage. modified: mysql-test/r/grant4.result mysql-test/t/grant4.test sql/sql_admin.cc sql/sql_parse.cc === modified file 'mysql-test/r/grant4.result' --- a/mysql-test/r/grant4.result 2010-02-20 10:07:32 +0000 +++ b/mysql-test/r/grant4.result 2010-12-01 10:07:22 +0000 @@ -121,3 +121,60 @@ View Create View character_set_client co v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `t_select_priv`.`a` AS `a`,`t_select_priv`.`b` AS `b` from `t_select_priv` latin1 latin1_swedish_ci drop database mysqltest_db1; drop user mysqltest_u1@localhost; +# +# Additional coverage for refactoring which is made as part +# of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege +# to allow temp table operations". +# +# Check that for statements like CHECK/REPAIR and OPTIMIZE TABLE +# privileges for all tables involved are checked before processing +# any tables. Doing otherwise, i.e. checking privileges for table +# right before processing it might result in lost results for tables +# which were processed by the time when table for which privileges +# are insufficient are discovered. +# +call mtr.add_suppression("Got an error from thread_id=.*ha_myisam.cc:"); +call mtr.add_suppression("MySQL thread id .*, query id .* localhost.*mysqltest_u1 Checking table"); +drop database if exists mysqltest_db1; +create database mysqltest_db1; +# Create tables which we are going to CHECK/REPAIR. +create table mysqltest_db1.t1 (a int, key(a)) engine=myisam; +create table mysqltest_db1.t2 (b int); +insert into mysqltest_db1.t1 values (1), (2); +insert into mysqltest_db1.t2 values (1); +# Create user which will try to do this. +create user mysqltest_u1@localhost; +grant insert, select on mysqltest_db1.t1 to mysqltest_u1@localhost; +# Corrupt t1 by replacing t1.MYI with a corrupt + unclosed one created +# by doing: 'create table t1 (a int key(a))' +# head -c1024 t1.MYI > corrupt_t1.MYI +flush table mysqltest_db1.t1; +# Switching to connection 'con1'. +check table mysqltest_db1.t1; +Table Op Msg_type Msg_text +mysqltest_db1.t1 check warning 1 client is using or hasn't closed the table properly +mysqltest_db1.t1 check error Size of indexfile is: 1024 Should be: 2048 +mysqltest_db1.t1 check warning Size of datafile is: 14 Should be: 7 +mysqltest_db1.t1 check error Corrupt +# The below statement should fail before repairing t1. +# Otherwise info about such repair will be missing from its result-set. +repair table mysqltest_db1.t1, mysqltest_db1.t2; +ERROR 42000: SELECT, INSERT command denied to user 'mysqltest_u1'@'localhost' for table 't2' +# The same is true for CHECK TABLE statement. +check table mysqltest_db1.t1, mysqltest_db1.t2; +ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't2' +check table mysqltest_db1.t1; +Table Op Msg_type Msg_text +mysqltest_db1.t1 check warning Table is marked as crashed +mysqltest_db1.t1 check warning 1 client is using or hasn't closed the table properly +mysqltest_db1.t1 check error Size of indexfile is: 1024 Should be: 2048 +mysqltest_db1.t1 check warning Size of datafile is: 14 Should be: 7 +mysqltest_db1.t1 check error Corrupt +repair table mysqltest_db1.t1; +Table Op Msg_type Msg_text +mysqltest_db1.t1 repair warning Number of rows changed from 1 to 2 +mysqltest_db1.t1 repair status OK +# Clean-up. +# Switching to connection 'default'. +drop database mysqltest_db1; +drop user mysqltest_u1@localhost; === modified file 'mysql-test/t/grant4.test' --- a/mysql-test/t/grant4.test 2009-10-19 12:58:13 +0000 +++ b/mysql-test/t/grant4.test 2010-12-01 10:07:22 +0000 @@ -144,3 +144,62 @@ connection default; disconnect con1; drop database mysqltest_db1; drop user mysqltest_u1@localhost; + + +--echo # +--echo # Additional coverage for refactoring which is made as part +--echo # of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege +--echo # to allow temp table operations". +--echo # +--echo # Check that for statements like CHECK/REPAIR and OPTIMIZE TABLE +--echo # privileges for all tables involved are checked before processing +--echo # any tables. Doing otherwise, i.e. checking privileges for table +--echo # right before processing it might result in lost results for tables +--echo # which were processed by the time when table for which privileges +--echo # are insufficient are discovered. +--echo # +call mtr.add_suppression("Got an error from thread_id=.*ha_myisam.cc:"); +call mtr.add_suppression("MySQL thread id .*, query id .* localhost.*mysqltest_u1 Checking table"); +--disable_warnings +drop database if exists mysqltest_db1; +--enable_warnings +let $MYSQLD_DATADIR = `SELECT @@datadir`; +create database mysqltest_db1; +--echo # Create tables which we are going to CHECK/REPAIR. +create table mysqltest_db1.t1 (a int, key(a)) engine=myisam; +create table mysqltest_db1.t2 (b int); +insert into mysqltest_db1.t1 values (1), (2); +insert into mysqltest_db1.t2 values (1); +--echo # Create user which will try to do this. +create user mysqltest_u1@localhost; +grant insert, select on mysqltest_db1.t1 to mysqltest_u1@localhost; +connect (con1,localhost,mysqltest_u1,,); +connection default; + +--echo # Corrupt t1 by replacing t1.MYI with a corrupt + unclosed one created +--echo # by doing: 'create table t1 (a int key(a))' +--echo # head -c1024 t1.MYI > corrupt_t1.MYI +flush table mysqltest_db1.t1; +--remove_file $MYSQLD_DATADIR/mysqltest_db1/t1.MYI +--copy_file std_data/corrupt_t1.MYI $MYSQLD_DATADIR/mysqltest_db1/t1.MYI + +--echo # Switching to connection 'con1'. +connection con1; +check table mysqltest_db1.t1; +--echo # The below statement should fail before repairing t1. +--echo # Otherwise info about such repair will be missing from its result-set. +--error ER_TABLEACCESS_DENIED_ERROR +repair table mysqltest_db1.t1, mysqltest_db1.t2; +--echo # The same is true for CHECK TABLE statement. +--error ER_TABLEACCESS_DENIED_ERROR +check table mysqltest_db1.t1, mysqltest_db1.t2; +check table mysqltest_db1.t1; +repair table mysqltest_db1.t1; + +--echo # Clean-up. +disconnect con1; +--source include/wait_until_disconnected.inc +--echo # Switching to connection 'default'. +connection default; +drop database mysqltest_db1; +drop user mysqltest_u1@localhost; === modified file 'sql/sql_admin.cc' --- a/sql/sql_admin.cc 2010-11-29 14:13:07 +0000 +++ b/sql/sql_admin.cc 2010-12-01 10:07:22 +0000 @@ -261,8 +261,6 @@ static bool mysql_admin_table(THD* thd, HA_CHECK_OPT* check_opt, const char *operator_name, thr_lock_type lock_type, - bool any_priv_will_do, - ulong op_privs, bool open_for_modify, bool no_warnings_for_error, uint extra_open_options, @@ -293,6 +291,12 @@ static bool mysql_admin_table(THD* thd, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); + /* + Close all temporary tables which were pre-open to simplify + privilege checking. + */ + close_thread_tables(thd); + for (table= tables; table; table= table->next_local) { char table_name[NAME_LEN*2+2]; @@ -300,29 +304,6 @@ static bool mysql_admin_table(THD* thd, bool fatal_error=0; bool open_error; - /* - Here we need to open list of tables (one table is not enough) because - of merge tables: children of merge tables must be opened here. - */ - - TABLE_LIST *next_global_tl= table->next_global; - - if (open_and_process_temporary_table_list(thd, table)) - DBUG_RETURN(TRUE); - - TABLE_LIST *last_added_tl; - - for (last_added_tl= table; - last_added_tl && last_added_tl->next_global != next_global_tl; - last_added_tl= last_added_tl->next_global) - ; - - if (op_privs) - { - if (check_table_access(thd, op_privs, table, any_priv_will_do, 1, FALSE)) - DBUG_RETURN(TRUE); - } - DBUG_PRINT("admin", ("table: '%s'.'%s'", table->db, table->table_name)); DBUG_PRINT("admin", ("extra_open_options: %u", extra_open_options)); strxmov(table_name, db, ".", table->table_name, NullS); @@ -338,10 +319,11 @@ static bool mysql_admin_table(THD* thd, MDL_SHARED_NO_READ_WRITE : MDL_SHARED_READ); /* open only one table from local list of command */ { - TABLE_LIST *next_global_saved= last_added_tl->next_global; - TABLE_LIST *next_local_saved= last_added_tl->next_local; - last_added_tl->next_global= NULL; - last_added_tl->next_local= NULL; + TABLE_LIST *save_next_global, *save_next_local; + save_next_global= table->next_global; + table->next_global= 0; + save_next_local= table->next_local; + table->next_local= 0; select->table_list.first= table; /* Time zone tables and SP tables can be add to lex->query_tables list, @@ -362,10 +344,14 @@ static bool mysql_admin_table(THD* thd, if (view_operator_func == NULL) table->required_type=FRMTYPE_TABLE; - open_error= open_and_lock_tables(thd, table, TRUE, 0); + open_error= open_and_process_temporary_table_list(thd, table); + + if (! open_error) + open_error= open_and_lock_tables(thd, table, TRUE, 0); + thd->no_warnings_for_error= 0; - last_added_tl->next_global= next_global_saved; - last_added_tl->next_local= next_local_saved; + table->next_global= save_next_global; + table->next_local= save_next_local; thd->open_options&= ~extra_open_options; } @@ -926,10 +912,8 @@ bool mysql_assign_to_keycache(THD* thd, mysql_mutex_unlock(&LOCK_global_system_variables); check_opt.key_cache= key_cache; DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt, - "assign_to_keycache", TL_READ_NO_INSERT, - FALSE, 0, - FALSE, FALSE, 0, NULL, - &handler::assign_to_keycache, NULL)); + "assign_to_keycache", TL_READ_NO_INSERT, 0, 0, + 0, 0, &handler::assign_to_keycache, 0)); } @@ -955,10 +939,8 @@ bool mysql_preload_keys(THD* thd, TABLE_ outdated information if parallel inserts into cache blocks happen. */ DBUG_RETURN(mysql_admin_table(thd, tables, 0, - "preload_keys", TL_READ_NO_INSERT, - FALSE, 0, - FALSE, FALSE, 0, NULL, - &handler::preload_keys, NULL)); + "preload_keys", TL_READ_NO_INSERT, 0, 0, 0, 0, + &handler::preload_keys, 0)); } @@ -969,12 +951,13 @@ bool Sql_cmd_analyze_table::execute(THD thr_lock_type lock_type = TL_READ_NO_INSERT; DBUG_ENTER("Sql_cmd_analyze_table::execute"); + if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table, + FALSE, UINT_MAX, FALSE)) + goto error; thd->enable_slow_log= opt_log_slow_admin_statements; res= mysql_admin_table(thd, first_table, &thd->lex->check_opt, - "analyze", lock_type, - FALSE, SELECT_ACL | INSERT_ACL, - TRUE, FALSE, 0, NULL, &handler::ha_analyze, NULL); - + "analyze", lock_type, 1, 0, 0, 0, + &handler::ha_analyze, 0); /* ! we write after unlocking the table */ if (!res && !thd->lex->no_write_to_binlog) { @@ -986,6 +969,7 @@ bool Sql_cmd_analyze_table::execute(THD thd->lex->select_lex.table_list.first= first_table; thd->lex->query_tables= first_table; +error: DBUG_RETURN(res); } @@ -1003,9 +987,7 @@ bool Sql_cmd_check_table::execute(THD *t thd->enable_slow_log= opt_log_slow_admin_statements; res= mysql_admin_table(thd, first_table, &thd->lex->check_opt, "check", - lock_type, - TRUE, SELECT_ACL, - FALSE, FALSE, HA_OPEN_FOR_REPAIR, NULL, + lock_type, 0, 0, HA_OPEN_FOR_REPAIR, 0, &handler::ha_check, &view_checksum); thd->lex->select_lex.table_list.first= first_table; @@ -1029,9 +1011,8 @@ bool Sql_cmd_optimize_table::execute(THD res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ? mysql_recreate_table(thd, first_table) : mysql_admin_table(thd, first_table, &thd->lex->check_opt, - "optimize", TL_WRITE, - FALSE, SELECT_ACL | INSERT_ACL, - TRUE, FALSE, 0, NULL, &handler::ha_optimize, 0); + "optimize", TL_WRITE, 1, 0, 0, 0, + &handler::ha_optimize, 0); /* ! we write after unlocking the table */ if (!res && !thd->lex->no_write_to_binlog) { @@ -1059,12 +1040,10 @@ bool Sql_cmd_repair_table::execute(THD * goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res= mysql_admin_table(thd, first_table, &thd->lex->check_opt, "repair", - TL_WRITE, - FALSE, SELECT_ACL| INSERT_ACL, - TRUE, + TL_WRITE, 1, test(thd->lex->check_opt.sql_flags & TT_USEFRM), HA_OPEN_FOR_REPAIR, &prepare_for_repair, - &handler::ha_repair, NULL); + &handler::ha_repair, 0); /* ! we write after unlocking the table */ if (!res && !thd->lex->no_write_to_binlog) === modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2010-11-29 14:13:07 +0000 +++ b/sql/sql_parse.cc 2010-12-01 10:07:22 +0000 @@ -476,6 +476,12 @@ void init_update_queries(void) sql_command_flags[SQLCOM_DO]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_CALL]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_CHECKSUM]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_ANALYZE]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_CHECK]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_OPTIMIZE]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_REPAIR]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_PRELOAD_KEYS]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_ASSIGN_TO_KEYCACHE]|= CF_PREOPEN_TMP_TABLES; /* DDL statements should start with closing opened handlers. --===============0270261209== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/dmitry.lenev@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: dmitry.lenev@stripped # target_branch: file:///home/dlenev/src/bzr/mysql-trunk-bugfixing-\ # bug27480/ # testament_sha1: 1ea6bd0428a2889bf2d759d54e79fa779b302c40 # timestamp: 2010-12-01 13:07:39 +0300 # base_revision_id: dmitry.lenev@stripped\ # is634uoi3h04egsg # # Begin bundle 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 MuBrNSMmbU6JxP31Qzp2f6F/+LuSKcKEhsUIU9A= --===============0270261209==--