diff options
author | Igor Babaev <igor@askmonty.org> | 2017-11-14 12:22:30 -0800 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2017-11-14 12:23:31 -0800 |
commit | 3afc9629fd84fbbc615f02aac0154e6b5ba92168 (patch) | |
tree | 9445aa9d8ee86603d34577344e4e82912d1a85b3 | |
parent | 24184938ad9954f25c082a1afd74a053a8ab6d8c (diff) | |
download | mariadb-git-3afc9629fd84fbbc615f02aac0154e6b5ba92168.tar.gz |
Fixed bug mdev-13453 Executing a query via CTE requires more permissions
than the query itself
ACL checks were not properly supported for tables used in CTE
specifications. This patch fixes the problem.
-rw-r--r-- | mysql-test/r/cte_nonrecursive.result | 58 | ||||
-rw-r--r-- | mysql-test/t/cte_nonrecursive.test | 51 | ||||
-rw-r--r-- | sql/sql_acl.cc | 4 | ||||
-rw-r--r-- | sql/sql_cte.cc | 3 | ||||
-rw-r--r-- | sql/sql_parse.cc | 8 |
5 files changed, 123 insertions, 1 deletions
diff --git a/mysql-test/r/cte_nonrecursive.result b/mysql-test/r/cte_nonrecursive.result index ebe1aae1e8f..21a1fa3164f 100644 --- a/mysql-test/r/cte_nonrecursive.result +++ b/mysql-test/r/cte_nonrecursive.result @@ -1147,3 +1147,61 @@ SELECT * FROM cte_test; a 1 DROP VIEW cte_test; +# +# MDEV-13453: privileges checking for CTE +# +create database db; +use db; +create table t1 (i int); +insert into t1 +values (3), (7), (1), (4), (2), (3), (1); +create table t2 (a int, b int); +insert into t2 +values (3,10), (7,11), (1,17), (4,15), (2,11), (3,10), (1,15); +create user foo@localhost; +grant SELECT on db.t1 to foo@localhost; +grant SELECT(a) on db.t2 to foo@localhost; +connect con1,localhost,foo,,; +use db; +with cte as (select * from t1 where i < 4) +select * from cte; +i +3 +1 +2 +3 +1 +with cte as (select * from t1 where i < 4 group by i) +select * from cte; +i +1 +2 +3 +with cte as (select * from t1 where i < 4) +select * from cte cte1 where i < 2 union select * from cte cte2 where i > 2; +i +1 +3 +with cte as (select * from t1 where i < 4 group by i) +select * from cte cte1 where i < 2 union select * from cte cte2 where i > 2; +i +1 +3 +with cte as (select b from t2 where a < 4) +select * from cte cte1 where b < 15 union select * from cte cte2 where b > 15; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'b' in table 't2' +with cte as (select a from t2 where a < 4) +select * from cte cte1 where a < 2 union select * from cte cte2 where a > 2; +a +1 +3 +connection default; +revoke SELECT on db.t1 from foo@localhost; +connection con1; +with cte as (select * from t1 where i < 4) +select * from cte; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1' +disconnect con1; +connection default; +drop database db; +drop user foo@localhost; diff --git a/mysql-test/t/cte_nonrecursive.test b/mysql-test/t/cte_nonrecursive.test index 742e8f6e4d7..03e6e298fa8 100644 --- a/mysql-test/t/cte_nonrecursive.test +++ b/mysql-test/t/cte_nonrecursive.test @@ -790,3 +790,54 @@ SHOW CREATE VIEW cte_test; SELECT * FROM cte_test; DROP VIEW cte_test; + +--echo # +--echo # MDEV-13453: privileges checking for CTE +--echo # + +create database db; +use db; +create table t1 (i int); +insert into t1 + values (3), (7), (1), (4), (2), (3), (1); + +create table t2 (a int, b int); +insert into t2 + values (3,10), (7,11), (1,17), (4,15), (2,11), (3,10), (1,15); + +create user foo@localhost; +grant SELECT on db.t1 to foo@localhost; +grant SELECT(a) on db.t2 to foo@localhost; + +--connect (con1,localhost,foo,,) +use db; +with cte as (select * from t1 where i < 4) + select * from cte; +with cte as (select * from t1 where i < 4 group by i) + select * from cte; +with cte as (select * from t1 where i < 4) + select * from cte cte1 where i < 2 union select * from cte cte2 where i > 2; +with cte as (select * from t1 where i < 4 group by i) + select * from cte cte1 where i < 2 union select * from cte cte2 where i > 2; + +--error ER_COLUMNACCESS_DENIED_ERROR +with cte as (select b from t2 where a < 4) + select * from cte cte1 where b < 15 union select * from cte cte2 where b > 15; +with cte as (select a from t2 where a < 4) + select * from cte cte1 where a < 2 union select * from cte cte2 where a > 2; + +--connection default +revoke SELECT on db.t1 from foo@localhost; + +--connection con1 + +--error ER_TABLEACCESS_DENIED_ERROR +with cte as (select * from t1 where i < 4) + select * from cte; + +# Cleanup +--disconnect con1 + +--connection default +drop database db; +drop user foo@localhost; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 555865804f9..74f06e7654d 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7557,6 +7557,10 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, tl->correspondent_table ? tl->correspondent_table : tl; sctx= t_ref->security_ctx ? t_ref->security_ctx : thd->security_ctx; + if (tl->with || + (tl->with= tl->select_lex->find_table_def_in_with_clauses(tl))) + continue; + const ACL_internal_table_access *access= get_cached_table_access(&t_ref->grant.m_internal, t_ref->get_db_name(), diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 6fe08e3c0ed..e1bd455830d 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -823,9 +823,10 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd, tbl; tbl= tbl->next_global) { - tbl->grant.privilege= with_table->grant.privilege; spec_tables_tail= tbl; } + if (check_table_access(thd, SELECT_ACL, spec_tables, FALSE, UINT_MAX, FALSE)) + goto err; if (spec_tables) { if (with_table->next_global) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index bf5144bfda6..fff58427aff 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3443,6 +3443,14 @@ mysql_execute_command(THD *thd) ulong privileges_requested= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL; + /* + The same function must be called for DML commands + when CTEs are supported in DML statements + */ + res= check_dependencies_in_with_clauses(thd->lex->with_clauses_list); + if (res) + break; + if (all_tables) res= check_table_access(thd, privileges_requested, |