Bug #20777016: DELETE CHECKS PRIVILEGES ON THE WRONG

               DATABASE WHEN USING TABLE ALIASES

Issue:
-----
When using table aliases for deleting, MySQL checks
privileges against the current database and not the
privileges on the actual table or database the table
resides.


SOLUTION:
---------
While checking privileges for multi-deletes,
correspondent_table should be used since it points to the
correct table and database.
parent 49667f04
......@@ -4612,16 +4612,19 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
tl && number-- && tl != first_not_own_table;
tl= tl->next_global)
{
sctx = test(tl->security_ctx) ? tl->security_ctx : thd->security_ctx;
TABLE_LIST *const t_ref=
tl->correspondent_table ? tl->correspondent_table : tl;
sctx = test(t_ref->security_ctx) ? t_ref->security_ctx :
thd->security_ctx;
const ACL_internal_table_access *access=
get_cached_table_access(&tl->grant.m_internal,
tl->get_db_name(),
tl->get_table_name());
get_cached_table_access(&t_ref->grant.m_internal,
t_ref->get_db_name(),
t_ref->get_table_name());
if (access)
{
switch(access->check(orig_want_access, &tl->grant.privilege))
switch(access->check(orig_want_access, &t_ref->grant.privilege))
{
case ACL_INTERNAL_ACCESS_GRANTED:
/*
......@@ -4645,34 +4648,34 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
if (!want_access)
continue; // ok
if (!(~tl->grant.privilege & want_access) ||
tl->is_anonymous_derived_table() || tl->schema_table)
if (!(~t_ref->grant.privilege & want_access) ||
t_ref->is_anonymous_derived_table() || t_ref->schema_table)
{
/*
It is subquery in the FROM clause. VIEW set tl->derived after
It is subquery in the FROM clause. VIEW set t_ref->derived after
table opening, but this function always called before table opening.
*/
if (!tl->referencing_view)
if (!t_ref->referencing_view)
{
/*
If it's a temporary table created for a subquery in the FROM
clause, or an INFORMATION_SCHEMA table, drop the request for
a privilege.
*/
tl->grant.want_privilege= 0;
t_ref->grant.want_privilege= 0;
}
continue;
}
GRANT_TABLE *grant_table= table_hash_search(sctx->get_host()->ptr(),
sctx->get_ip()->ptr(),
tl->get_db_name(),
t_ref->get_db_name(),
sctx->priv_user,
tl->get_table_name(),
t_ref->get_table_name(),
FALSE);
if (!grant_table)
{
want_access &= ~tl->grant.privilege;
want_access &= ~t_ref->grant.privilege;
goto err; // No grants
}
......@@ -4683,17 +4686,17 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
if (any_combination_will_do)
continue;
tl->grant.grant_table= grant_table; // Remember for column test
tl->grant.version= grant_version;
tl->grant.privilege|= grant_table->privs;
tl->grant.want_privilege= ((want_access & COL_ACLS) & ~tl->grant.privilege);
t_ref->grant.grant_table= grant_table; // Remember for column test
t_ref->grant.version= grant_version;
t_ref->grant.privilege|= grant_table->privs;
t_ref->grant.want_privilege= ((want_access & COL_ACLS) & ~t_ref->grant.privilege);
if (!(~tl->grant.privilege & want_access))
if (!(~t_ref->grant.privilege & want_access))
continue;
if (want_access & ~(grant_table->cols | tl->grant.privilege))
if (want_access & ~(grant_table->cols | t_ref->grant.privilege))
{
want_access &= ~(grant_table->cols | tl->grant.privilege);
want_access &= ~(grant_table->cols | t_ref->grant.privilege);
goto err; // impossible
}
}
......
......@@ -5069,9 +5069,12 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
for (; i < number && tables != first_not_own_table && tables;
tables= tables->next_global, i++)
{
TABLE_LIST *const table_ref= tables->correspondent_table ?
tables->correspondent_table : tables;
ulong want_access= requirements;
if (tables->security_ctx)
sctx= tables->security_ctx;
if (table_ref->security_ctx)
sctx= table_ref->security_ctx;
else
sctx= backup_ctx;
......@@ -5079,26 +5082,26 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
Register access for view underlying table.
Remove SHOW_VIEW_ACL, because it will be checked during making view
*/
tables->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
table_ref->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
if (tables->schema_table_reformed)
if (table_ref->schema_table_reformed)
{
if (check_show_access(thd, tables))
if (check_show_access(thd, table_ref))
goto deny;
continue;
}
DBUG_PRINT("info", ("derived: %d view: %d", tables->derived != 0,
tables->view != 0));
if (tables->is_anonymous_derived_table() ||
(tables->table && tables->table->s &&
(int)tables->table->s->tmp_table))
DBUG_PRINT("info", ("derived: %d view: %d", table_ref->derived != 0,
table_ref->view != 0));
if (table_ref->is_anonymous_derived_table() ||
(table_ref->table && table_ref->table->s &&
(int)table_ref->table->s->tmp_table))
continue;
thd->security_ctx= sctx;
if (check_access(thd, want_access, tables->get_db_name(),
&tables->grant.privilege,
&tables->grant.m_internal,
if (check_access(thd, want_access, table_ref->get_db_name(),
&table_ref->grant.privilege,
&table_ref->grant.m_internal,
0, no_errors))
goto deny;
}
......
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