summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <antony@ltantony.rdg.cyberkinetica.homeunix.net>2004-12-18 15:12:10 +0000
committerunknown <antony@ltantony.rdg.cyberkinetica.homeunix.net>2004-12-18 15:12:10 +0000
commit02453262bcecf06408382a4cffec162cc0d4d674 (patch)
treec553786f19f99a3ccca5eda7e06d7cf8a2773621
parent4e8e1ef30d393920da36626d6eb272ceca4b5578 (diff)
parent047f7904715c1dcd9fc2ada7052e0237e6e97861 (diff)
downloadmariadb-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.sh3
-rw-r--r--mysql-test/r/grant.result64
-rw-r--r--mysql-test/t/grant.test72
-rw-r--r--sql/sql_select.cc10
-rw-r--r--sql/sql_update.cc20
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))