Skip to content

Commit

Permalink
Fixed bug mdev-13453 Executing a query via CTE requires more permissions
Browse files Browse the repository at this point in the history
than the query itself

ACL checks were not properly supported for tables used in CTE
specifications. This patch fixes the problem.
  • Loading branch information
igorbabaev committed Nov 14, 2017
1 parent 2418493 commit 3afc962
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 1 deletion.
58 changes: 58 additions & 0 deletions mysql-test/r/cte_nonrecursive.result
Original file line number Diff line number Diff line change
Expand Up @@ -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;
51 changes: 51 additions & 0 deletions mysql-test/t/cte_nonrecursive.test
Original file line number Diff line number Diff line change
Expand Up @@ -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;
4 changes: 4 additions & 0 deletions sql/sql_acl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
3 changes: 2 additions & 1 deletion sql/sql_cte.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions sql/sql_parse.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 3afc962

Please sign in to comment.