Loading mysql-test/mysql-test-run.sh +2 −1 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ # Slightly updated by Monty # Cleaned up again by Matt # Fixed by Sergei # List of failed cases (--force) backported from 4.1 by Joerg # :-) #++ Loading mysql-test/r/grant.result +64 −0 Original line number Diff line number Diff line Loading @@ -341,3 +341,67 @@ select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv; Host Db User Table_name Column_name Column_priv drop user grant_user@localhost; drop table t1; create database mysqltest_1; create database mysqltest_2; create table mysqltest_1.t1 select 1 a, 2 q; create table mysqltest_1.t2 select 1 b, 2 r; create table mysqltest_2.t1 select 1 c, 2 s; create table mysqltest_2.t2 select 1 d, 2 t; grant update (a) on mysqltest_1.t1 to mysqltest_3@localhost; grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost; grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost; grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost; show grants for mysqltest_3@localhost; Grants for mysqltest_3@localhost GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost' GRANT SELECT (b) ON `mysqltest_1`.`t2` TO 'mysqltest_3'@'localhost' GRANT SELECT (c) ON `mysqltest_2`.`t1` TO 'mysqltest_3'@'localhost' GRANT UPDATE (a) ON `mysqltest_1`.`t1` TO 'mysqltest_3'@'localhost' GRANT UPDATE (d) ON `mysqltest_2`.`t2` TO 'mysqltest_3'@'localhost' update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1; ERROR 42000: UPDATE command denied to user 'mysqltest_3@localhost' for column 'q' in table 't1' update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1; ERROR 42000: SELECT command denied to user 'mysqltest_3@localhost' for column 'd' in table 't1' update mysqltest_2.t1, mysqltest_1.t2 set c=20 where b=1; ERROR 42000: UPDATE command denied to user 'mysqltest_3@localhost' for column 'c' in table 't1' update mysqltest_2.t1, mysqltest_2.t2 set d=10 where s=2; ERROR 42000: SELECT command denied to user 'mysqltest_3@localhost' for column 's' in table 't1' update mysqltest_1.t1, mysqltest_2.t2 set a=10,d=10; update mysqltest_1.t1, mysqltest_2.t1 set a=20 where c=20; select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2; a q b r 10 2 1 2 select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2; c s d t 1 2 10 2 revoke all on mysqltest_1.t1 from mysqltest_3@localhost; revoke all on mysqltest_1.t2 from mysqltest_3@localhost; revoke all on mysqltest_2.t1 from mysqltest_3@localhost; revoke all on mysqltest_2.t2 from mysqltest_3@localhost; grant all on mysqltest_2.* to mysqltest_3@localhost; grant select on *.* to mysqltest_3@localhost; flush privileges; use mysqltest_1; update mysqltest_2.t1, mysqltest_2.t2 set c=500,d=600; update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200; ERROR 42000: UPDATE command denied to user 'mysqltest_3@localhost' for column 'a' in table 't1' use mysqltest_2; update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200; ERROR 42000: Access denied for user 'mysqltest_3@localhost' to database 'mysqltest_1' update mysqltest_2.t1, mysqltest_1.t2 set c=100,b=200; ERROR 42000: Access denied for user 'mysqltest_3@localhost' to database 'mysqltest_1' update mysqltest_1.t1, mysqltest_2.t2 set a=100,d=200; ERROR 42000: Access denied for user 'mysqltest_3@localhost' to database 'mysqltest_1' select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2; a q b r 10 2 1 2 select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2; c s d t 500 2 600 2 delete from mysql.user where user='mysqltest_3'; delete from mysql.db where user="mysqltest_3"; delete from mysql.tables_priv where user="mysqltest_3"; delete from mysql.columns_priv where user="mysqltest_3"; flush privileges; drop database mysqltest_1; drop database mysqltest_2; mysql-test/t/grant.test +72 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ drop table if exists t1; --enable_warnings connect (master,localhost,root,,); connection master; SET NAMES binary; # Loading Loading @@ -280,3 +282,73 @@ show grants for grant_user@localhost; select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv; drop user grant_user@localhost; drop table t1; # # Bug#7391: Cross-database multi-table UPDATE security problem # create database mysqltest_1; create database mysqltest_2; create table mysqltest_1.t1 select 1 a, 2 q; create table mysqltest_1.t2 select 1 b, 2 r; create table mysqltest_2.t1 select 1 c, 2 s; create table mysqltest_2.t2 select 1 d, 2 t; #test the column privileges grant update (a) on mysqltest_1.t1 to mysqltest_3@localhost; grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost; grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost; grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost; connect (conn1,localhost,mysqltest_3,,); connection conn1; show grants for mysqltest_3@localhost; --error 1143 update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1; --error 1143 update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1; --error 1143 update mysqltest_2.t1, mysqltest_1.t2 set c=20 where b=1; --error 1143 update mysqltest_2.t1, mysqltest_2.t2 set d=10 where s=2; #the following two should work update mysqltest_1.t1, mysqltest_2.t2 set a=10,d=10; update mysqltest_1.t1, mysqltest_2.t1 set a=20 where c=20; connection master; select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2; select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2; revoke all on mysqltest_1.t1 from mysqltest_3@localhost; revoke all on mysqltest_1.t2 from mysqltest_3@localhost; revoke all on mysqltest_2.t1 from mysqltest_3@localhost; revoke all on mysqltest_2.t2 from mysqltest_3@localhost; #test the db/table level privileges grant all on mysqltest_2.* to mysqltest_3@localhost; grant select on *.* to mysqltest_3@localhost; flush privileges; disconnect conn1; connect (conn2,localhost,mysqltest_3,,); connection conn2; use mysqltest_1; update mysqltest_2.t1, mysqltest_2.t2 set c=500,d=600; # the following failed before, should fail now. --error 1143 update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200; use mysqltest_2; #the following used to succeed, it must fail now. --error 1044 update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200; --error 1044 update mysqltest_2.t1, mysqltest_1.t2 set c=100,b=200; --error 1044 update mysqltest_1.t1, mysqltest_2.t2 set a=100,d=200; #lets see the result connection master; select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2; select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2; delete from mysql.user where user='mysqltest_3'; delete from mysql.db where user="mysqltest_3"; delete from mysql.tables_priv where user="mysqltest_3"; delete from mysql.columns_priv where user="mysqltest_3"; flush privileges; drop database mysqltest_1; drop database mysqltest_2; sql/sql_select.cc +2 −8 Original line number Diff line number Diff line Loading @@ -6005,10 +6005,7 @@ join_read_system(JOIN_TAB *tab) { if (error != HA_ERR_END_OF_FILE) return report_error(table, error); if (tab->on_expr) mark_as_null_row(tab->table); else table->null_row=1; // Why do this for inner join? empty_record(table); // Make empty record return -1; } Loading Loading @@ -6038,10 +6035,7 @@ join_read_const(JOIN_TAB *tab) } if (error) { if (tab->on_expr) mark_as_null_row(tab->table); else table->null_row=1; empty_record(table); if (error != HA_ERR_KEY_NOT_FOUND) return report_error(table, error); Loading sql/sql_update.cc +18 −2 Original line number Diff line number Diff line Loading @@ -553,7 +553,9 @@ int mysql_multi_update(THD *thd, */ for (tl= update_list; tl; tl= tl->next) { TABLE_LIST *save= tl->next; TABLE *table= tl->table; uint wants; /* if table will be updated then check that it is unique */ if (table->map & update_tables) { Loading @@ -571,17 +573,31 @@ int mysql_multi_update(THD *thd, DBUG_PRINT("info",("setting table `%s` for update", tl->alias)); tl->lock_type= thd->lex->multi_lock_option; tl->updating= 1; wants= UPDATE_ACL; } else { DBUG_PRINT("info",("setting table `%s` for read-only", tl->alias)); tl->lock_type= TL_READ; tl->updating= 0; wants= SELECT_ACL; } if (tl->derived) derived_tables|= table->map; else if (!using_lock_tables) else { tl->next= 0; if (!using_lock_tables) tl->table->reginfo.lock_type= tl->lock_type; if (check_access(thd, wants, tl->db, &tl->grant.privilege, 0, 0) || (grant_option && check_grant(thd, wants, tl, 0, 0, 0))) { tl->next= save; DBUG_RETURN(0); } tl->next= save; } } if (thd->lex->derived_tables && (update_tables & derived_tables)) Loading Loading
mysql-test/mysql-test-run.sh +2 −1 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ # Slightly updated by Monty # Cleaned up again by Matt # Fixed by Sergei # List of failed cases (--force) backported from 4.1 by Joerg # :-) #++ Loading
mysql-test/r/grant.result +64 −0 Original line number Diff line number Diff line Loading @@ -341,3 +341,67 @@ select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv; Host Db User Table_name Column_name Column_priv drop user grant_user@localhost; drop table t1; create database mysqltest_1; create database mysqltest_2; create table mysqltest_1.t1 select 1 a, 2 q; create table mysqltest_1.t2 select 1 b, 2 r; create table mysqltest_2.t1 select 1 c, 2 s; create table mysqltest_2.t2 select 1 d, 2 t; grant update (a) on mysqltest_1.t1 to mysqltest_3@localhost; grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost; grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost; grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost; show grants for mysqltest_3@localhost; Grants for mysqltest_3@localhost GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost' GRANT SELECT (b) ON `mysqltest_1`.`t2` TO 'mysqltest_3'@'localhost' GRANT SELECT (c) ON `mysqltest_2`.`t1` TO 'mysqltest_3'@'localhost' GRANT UPDATE (a) ON `mysqltest_1`.`t1` TO 'mysqltest_3'@'localhost' GRANT UPDATE (d) ON `mysqltest_2`.`t2` TO 'mysqltest_3'@'localhost' update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1; ERROR 42000: UPDATE command denied to user 'mysqltest_3@localhost' for column 'q' in table 't1' update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1; ERROR 42000: SELECT command denied to user 'mysqltest_3@localhost' for column 'd' in table 't1' update mysqltest_2.t1, mysqltest_1.t2 set c=20 where b=1; ERROR 42000: UPDATE command denied to user 'mysqltest_3@localhost' for column 'c' in table 't1' update mysqltest_2.t1, mysqltest_2.t2 set d=10 where s=2; ERROR 42000: SELECT command denied to user 'mysqltest_3@localhost' for column 's' in table 't1' update mysqltest_1.t1, mysqltest_2.t2 set a=10,d=10; update mysqltest_1.t1, mysqltest_2.t1 set a=20 where c=20; select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2; a q b r 10 2 1 2 select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2; c s d t 1 2 10 2 revoke all on mysqltest_1.t1 from mysqltest_3@localhost; revoke all on mysqltest_1.t2 from mysqltest_3@localhost; revoke all on mysqltest_2.t1 from mysqltest_3@localhost; revoke all on mysqltest_2.t2 from mysqltest_3@localhost; grant all on mysqltest_2.* to mysqltest_3@localhost; grant select on *.* to mysqltest_3@localhost; flush privileges; use mysqltest_1; update mysqltest_2.t1, mysqltest_2.t2 set c=500,d=600; update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200; ERROR 42000: UPDATE command denied to user 'mysqltest_3@localhost' for column 'a' in table 't1' use mysqltest_2; update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200; ERROR 42000: Access denied for user 'mysqltest_3@localhost' to database 'mysqltest_1' update mysqltest_2.t1, mysqltest_1.t2 set c=100,b=200; ERROR 42000: Access denied for user 'mysqltest_3@localhost' to database 'mysqltest_1' update mysqltest_1.t1, mysqltest_2.t2 set a=100,d=200; ERROR 42000: Access denied for user 'mysqltest_3@localhost' to database 'mysqltest_1' select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2; a q b r 10 2 1 2 select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2; c s d t 500 2 600 2 delete from mysql.user where user='mysqltest_3'; delete from mysql.db where user="mysqltest_3"; delete from mysql.tables_priv where user="mysqltest_3"; delete from mysql.columns_priv where user="mysqltest_3"; flush privileges; drop database mysqltest_1; drop database mysqltest_2;
mysql-test/t/grant.test +72 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ drop table if exists t1; --enable_warnings connect (master,localhost,root,,); connection master; SET NAMES binary; # Loading Loading @@ -280,3 +282,73 @@ show grants for grant_user@localhost; select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv; drop user grant_user@localhost; drop table t1; # # Bug#7391: Cross-database multi-table UPDATE security problem # create database mysqltest_1; create database mysqltest_2; create table mysqltest_1.t1 select 1 a, 2 q; create table mysqltest_1.t2 select 1 b, 2 r; create table mysqltest_2.t1 select 1 c, 2 s; create table mysqltest_2.t2 select 1 d, 2 t; #test the column privileges grant update (a) on mysqltest_1.t1 to mysqltest_3@localhost; grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost; grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost; grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost; connect (conn1,localhost,mysqltest_3,,); connection conn1; show grants for mysqltest_3@localhost; --error 1143 update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1; --error 1143 update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1; --error 1143 update mysqltest_2.t1, mysqltest_1.t2 set c=20 where b=1; --error 1143 update mysqltest_2.t1, mysqltest_2.t2 set d=10 where s=2; #the following two should work update mysqltest_1.t1, mysqltest_2.t2 set a=10,d=10; update mysqltest_1.t1, mysqltest_2.t1 set a=20 where c=20; connection master; select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2; select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2; revoke all on mysqltest_1.t1 from mysqltest_3@localhost; revoke all on mysqltest_1.t2 from mysqltest_3@localhost; revoke all on mysqltest_2.t1 from mysqltest_3@localhost; revoke all on mysqltest_2.t2 from mysqltest_3@localhost; #test the db/table level privileges grant all on mysqltest_2.* to mysqltest_3@localhost; grant select on *.* to mysqltest_3@localhost; flush privileges; disconnect conn1; connect (conn2,localhost,mysqltest_3,,); connection conn2; use mysqltest_1; update mysqltest_2.t1, mysqltest_2.t2 set c=500,d=600; # the following failed before, should fail now. --error 1143 update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200; use mysqltest_2; #the following used to succeed, it must fail now. --error 1044 update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200; --error 1044 update mysqltest_2.t1, mysqltest_1.t2 set c=100,b=200; --error 1044 update mysqltest_1.t1, mysqltest_2.t2 set a=100,d=200; #lets see the result connection master; select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2; select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2; delete from mysql.user where user='mysqltest_3'; delete from mysql.db where user="mysqltest_3"; delete from mysql.tables_priv where user="mysqltest_3"; delete from mysql.columns_priv where user="mysqltest_3"; flush privileges; drop database mysqltest_1; drop database mysqltest_2;
sql/sql_select.cc +2 −8 Original line number Diff line number Diff line Loading @@ -6005,10 +6005,7 @@ join_read_system(JOIN_TAB *tab) { if (error != HA_ERR_END_OF_FILE) return report_error(table, error); if (tab->on_expr) mark_as_null_row(tab->table); else table->null_row=1; // Why do this for inner join? empty_record(table); // Make empty record return -1; } Loading Loading @@ -6038,10 +6035,7 @@ join_read_const(JOIN_TAB *tab) } if (error) { if (tab->on_expr) mark_as_null_row(tab->table); else table->null_row=1; empty_record(table); if (error != HA_ERR_KEY_NOT_FOUND) return report_error(table, error); Loading
sql/sql_update.cc +18 −2 Original line number Diff line number Diff line Loading @@ -553,7 +553,9 @@ int mysql_multi_update(THD *thd, */ for (tl= update_list; tl; tl= tl->next) { TABLE_LIST *save= tl->next; TABLE *table= tl->table; uint wants; /* if table will be updated then check that it is unique */ if (table->map & update_tables) { Loading @@ -571,17 +573,31 @@ int mysql_multi_update(THD *thd, DBUG_PRINT("info",("setting table `%s` for update", tl->alias)); tl->lock_type= thd->lex->multi_lock_option; tl->updating= 1; wants= UPDATE_ACL; } else { DBUG_PRINT("info",("setting table `%s` for read-only", tl->alias)); tl->lock_type= TL_READ; tl->updating= 0; wants= SELECT_ACL; } if (tl->derived) derived_tables|= table->map; else if (!using_lock_tables) else { tl->next= 0; if (!using_lock_tables) tl->table->reginfo.lock_type= tl->lock_type; if (check_access(thd, wants, tl->db, &tl->grant.privilege, 0, 0) || (grant_option && check_grant(thd, wants, tl, 0, 0, 0))) { tl->next= save; DBUG_RETURN(0); } tl->next= save; } } if (thd->lex->derived_tables && (update_tables & derived_tables)) Loading