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;
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;
......@@ -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;
......@@ -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(),
......
......@@ -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)
......
......@@ -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,
......
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