Commit 0c3723e1 authored by Sergei Golubchik's avatar Sergei Golubchik

Bug#31304432 "INSUFFICIENT PRIVILEGE CHECK BY LOCK TABLES"

`LOCK TABLES view_name` should require
* invoker to have SELECT and LOCK TABLES privileges on the view
* either invoker or definer (only if sql security definer) to
  have SELECT and LOCK TABLES privileges on the used tables/views.
parent 320a73f6
This diff is collapsed.
source include/not_embedded.inc;
#
# LOCK TABLES and privileges on views
#
create database mysqltest1;
create database mysqltest2;
create database mysqltest3;
create user invoker@localhost;
create user definer@localhost;
grant select,show view on mysqltest1.* to invoker@localhost;
grant select,show view on mysqltest1.* to definer@localhost;
grant select,show view on mysqltest2.* to invoker@localhost;
grant select,show view on mysqltest2.* to definer@localhost;
grant select,show view on mysqltest3.* to invoker@localhost;
grant select on performance_schema.* to definer@localhost;
create table mysqltest1.t1 (a int);
create definer=definer@localhost view mysqltest2.v2 as select * from mysqltest1.t1;
create definer=definer@localhost view mysqltest3.v3 as select * from mysqltest2.v2;
create definer=definer@localhost view mysqltest3.v3is as select schema_name from information_schema.schemata order by schema_name;
create definer=definer@localhost view mysqltest3.v3ps as select user from performance_schema.users where current_connections>0 order by user;
create definer=definer@localhost view mysqltest3.v3nt as select 1;
create definer=definer@localhost sql security invoker view mysqltest3.v3i as select * from mysqltest1.t1;
exec $MYSQL_DUMP --compact -B mysqltest1 mysqltest2 mysqltest3;
connect inv,localhost,invoker;
error ER_DBACCESS_DENIED_ERROR;
lock table mysqltest3.v3 write;
disconnect inv;
connection default;
grant lock tables on mysqltest3.* to invoker@localhost;
connect inv,localhost,invoker;
show create view mysqltest3.v3;
show create view mysqltest3.v3is;
show create view mysqltest3.v3ps;
show create view mysqltest3.v3nt;
show create view mysqltest3.v3i;
error ER_VIEW_INVALID;
lock table mysqltest3.v3 write;
error ER_VIEW_INVALID;
lock table mysqltest3.v3i write;
lock table mysqltest3.v3is write; select * from mysqltest3.v3is;
lock table mysqltest3.v3ps write; select * from mysqltest3.v3ps;
lock table mysqltest3.v3nt write; select * from mysqltest3.v3nt;
disconnect inv;
connection default;
grant lock tables on mysqltest2.* to invoker@localhost;
connect inv,localhost,invoker;
error ER_VIEW_INVALID;
lock table mysqltest3.v3 write;
error ER_VIEW_INVALID;
lock table mysqltest3.v3i write;
disconnect inv;
connection default;
grant lock tables on mysqltest1.* to definer@localhost;
connect inv,localhost,invoker;
lock table mysqltest3.v3 write; select * from mysqltest3.v3;
error ER_VIEW_INVALID;
lock table mysqltest3.v3i write;
disconnect inv;
connection default;
grant lock tables on mysqltest1.* to invoker@localhost;
connect inv,localhost,invoker;
lock table mysqltest3.v3i write; select * from mysqltest3.v3i;
disconnect inv;
connection default;
drop user invoker@localhost;
drop user definer@localhost;
drop database mysqltest1;
drop database mysqltest2;
drop database mysqltest3;
...@@ -2392,10 +2392,40 @@ static bool lock_tables_open_and_lock_tables(THD *thd, TABLE_LIST *tables) ...@@ -2392,10 +2392,40 @@ static bool lock_tables_open_and_lock_tables(THD *thd, TABLE_LIST *tables)
We don't set TABLE_LIST::lock_type in this case as this might result in We don't set TABLE_LIST::lock_type in this case as this might result in
extra warnings from THD::decide_logging_format() even though binary logging extra warnings from THD::decide_logging_format() even though binary logging
is totally irrelevant for LOCK TABLES. is totally irrelevant for LOCK TABLES.
Check privileges of view tables here, after views were opened.
Either definer or invoker has to have PRIV_LOCK_TABLES to be able to
lock view and its tables. For mysqldump (that locks views before dumping
their structures) compatibility we allow locking views that select
from I_S or P_S tables, but downrade the lock to TL_READ
*/ */
for (table= tables; table; table= table->next_global) for (table= tables; table; table= table->next_global)
{
if (!table->placeholder() && table->table->s->tmp_table) if (!table->placeholder() && table->table->s->tmp_table)
table->table->reginfo.lock_type= TL_WRITE; table->table->reginfo.lock_type= TL_WRITE;
else if (table->belong_to_view &&
check_single_table_access(thd, PRIV_LOCK_TABLES, table, 1))
{
if (table->grant.m_internal.m_schema_access)
table->lock_type= TL_READ;
else
{
bool error= true;
if (Security_context *sctx= table->security_ctx)
{
table->security_ctx= 0;
error= check_single_table_access(thd, PRIV_LOCK_TABLES, table, 1);
table->security_ctx= sctx;
}
if (error)
{
my_error(ER_VIEW_INVALID, MYF(0), table->belong_to_view->view_db.str,
table->belong_to_view->view_name.str);
goto err;
}
}
}
}
if (lock_tables(thd, tables, counter, 0) || if (lock_tables(thd, tables, counter, 0) ||
thd->locked_tables_list.init_locked_tables(thd)) thd->locked_tables_list.init_locked_tables(thd))
......
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