diff options
author | unknown <antony@ltantony.rdg.cyberkinetica.homeunix.net> | 2004-12-18 15:12:10 +0000 |
---|---|---|
committer | unknown <antony@ltantony.rdg.cyberkinetica.homeunix.net> | 2004-12-18 15:12:10 +0000 |
commit | 02453262bcecf06408382a4cffec162cc0d4d674 (patch) | |
tree | c553786f19f99a3ccca5eda7e06d7cf8a2773621 | |
parent | 4e8e1ef30d393920da36626d6eb272ceca4b5578 (diff) | |
parent | 047f7904715c1dcd9fc2ada7052e0237e6e97861 (diff) | |
download | mariadb-git-02453262bcecf06408382a4cffec162cc0d4d674.tar.gz |
Merge Bug#7391 from 4.0
mysql-test/r/update.result:
Auto merged
mysql-test/t/update.test:
Auto merged
sql/sql_select.cc:
Auto merged
mysql-test/mysql-test-run.sh:
Merge from 4.0
-rw-r--r-- | mysql-test/mysql-test-run.sh | 3 | ||||
-rw-r--r-- | mysql-test/r/grant.result | 64 | ||||
-rw-r--r-- | mysql-test/t/grant.test | 72 | ||||
-rw-r--r-- | sql/sql_select.cc | 10 | ||||
-rw-r--r-- | sql/sql_update.cc | 20 |
5 files changed, 158 insertions, 11 deletions
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 426b8b486be..93b1360846a 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -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 # :-) #++ @@ -1348,7 +1349,7 @@ run_testcase () result_file="$result_file$RESULT_EXT" fi if [ "$USE_MANAGER" = 1 ] ; then - many_slaves=`$EXPR \( \( $tname : rpl_failsafe \) != 0 \) \| \( \( $tname : rpl_chain_temp_table \) != 0 \)` + many_slaves=`$EXPR \( \( $tname : rpl_failsafe \) != 0 \) \| \( \( $tname : rpl_chain_temp_table \) != 0 \)` fi if $EXPR "$tname" '<' "$START_FROM" > /dev/null ; then #skip_test $tname diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index d163e1033fc..38f7ca13a4b 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -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; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 169dd03ad86..338711b8736 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -5,6 +5,8 @@ drop table if exists t1; --enable_warnings +connect (master,localhost,root,,); +connection master; SET NAMES binary; # @@ -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; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2d701e668cf..610a98d1983 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -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? + mark_as_null_row(tab->table); empty_record(table); // Make empty record return -1; } @@ -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; + mark_as_null_row(tab->table); empty_record(table); if (error != HA_ERR_KEY_NOT_FOUND) return report_error(table, error); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 6fc68142a12..2b27cff13e2 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -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) { @@ -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) - tl->table->reginfo.lock_type= tl->lock_type; + 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)) |