Commit 3afc9629 authored by Igor Babaev's avatar Igor Babaev

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.
parent 24184938
...@@ -1147,3 +1147,61 @@ SELECT * FROM cte_test; ...@@ -1147,3 +1147,61 @@ SELECT * FROM cte_test;
a a
1 1
DROP VIEW cte_test; 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;
...@@ -790,3 +790,54 @@ SHOW CREATE VIEW cte_test; ...@@ -790,3 +790,54 @@ SHOW CREATE VIEW cte_test;
SELECT * FROM cte_test; SELECT * FROM cte_test;
DROP VIEW 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;
...@@ -7557,6 +7557,10 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, ...@@ -7557,6 +7557,10 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
tl->correspondent_table ? tl->correspondent_table : tl; tl->correspondent_table ? tl->correspondent_table : tl;
sctx= t_ref->security_ctx ? t_ref->security_ctx : thd->security_ctx; 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= const ACL_internal_table_access *access=
get_cached_table_access(&t_ref->grant.m_internal, get_cached_table_access(&t_ref->grant.m_internal,
t_ref->get_db_name(), t_ref->get_db_name(),
......
...@@ -823,9 +823,10 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd, ...@@ -823,9 +823,10 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
tbl; tbl;
tbl= tbl->next_global) tbl= tbl->next_global)
{ {
tbl->grant.privilege= with_table->grant.privilege;
spec_tables_tail= tbl; spec_tables_tail= tbl;
} }
if (check_table_access(thd, SELECT_ACL, spec_tables, FALSE, UINT_MAX, FALSE))
goto err;
if (spec_tables) if (spec_tables)
{ {
if (with_table->next_global) if (with_table->next_global)
......
...@@ -3443,6 +3443,14 @@ mysql_execute_command(THD *thd) ...@@ -3443,6 +3443,14 @@ mysql_execute_command(THD *thd)
ulong privileges_requested= lex->exchange ? SELECT_ACL | FILE_ACL : ulong privileges_requested= lex->exchange ? SELECT_ACL | FILE_ACL :
SELECT_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) if (all_tables)
res= check_table_access(thd, res= check_table_access(thd,
privileges_requested, privileges_requested,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment