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.
This commit is contained in:
Igor Babaev 2017-11-14 12:22:30 -08:00
parent 24184938ad
commit 3afc9629fd
5 changed files with 123 additions and 1 deletions

View file

@ -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;

View file

@ -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;

View file

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

View file

@ -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)

View file

@ -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,