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, ...@@ -4612,16 +4612,19 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
tl && number-- && tl != first_not_own_table; tl && number-- && tl != first_not_own_table;
tl= tl->next_global) 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= const ACL_internal_table_access *access=
get_cached_table_access(&tl->grant.m_internal, get_cached_table_access(&t_ref->grant.m_internal,
tl->get_db_name(), t_ref->get_db_name(),
tl->get_table_name()); t_ref->get_table_name());
if (access) 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: case ACL_INTERNAL_ACCESS_GRANTED:
/* /*
...@@ -4645,34 +4648,34 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, ...@@ -4645,34 +4648,34 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
if (!want_access) if (!want_access)
continue; // ok continue; // ok
if (!(~tl->grant.privilege & want_access) || if (!(~t_ref->grant.privilege & want_access) ||
tl->is_anonymous_derived_table() || tl->schema_table) 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. 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 If it's a temporary table created for a subquery in the FROM
clause, or an INFORMATION_SCHEMA table, drop the request for clause, or an INFORMATION_SCHEMA table, drop the request for
a privilege. a privilege.
*/ */
tl->grant.want_privilege= 0; t_ref->grant.want_privilege= 0;
} }
continue; continue;
} }
GRANT_TABLE *grant_table= table_hash_search(sctx->get_host()->ptr(), GRANT_TABLE *grant_table= table_hash_search(sctx->get_host()->ptr(),
sctx->get_ip()->ptr(), sctx->get_ip()->ptr(),
tl->get_db_name(), t_ref->get_db_name(),
sctx->priv_user, sctx->priv_user,
tl->get_table_name(), t_ref->get_table_name(),
FALSE); FALSE);
if (!grant_table) if (!grant_table)
{ {
want_access &= ~tl->grant.privilege; want_access &= ~t_ref->grant.privilege;
goto err; // No grants goto err; // No grants
} }
...@@ -4683,17 +4686,17 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, ...@@ -4683,17 +4686,17 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
if (any_combination_will_do) if (any_combination_will_do)
continue; continue;
tl->grant.grant_table= grant_table; // Remember for column test t_ref->grant.grant_table= grant_table; // Remember for column test
tl->grant.version= grant_version; t_ref->grant.version= grant_version;
tl->grant.privilege|= grant_table->privs; t_ref->grant.privilege|= grant_table->privs;
tl->grant.want_privilege= ((want_access & COL_ACLS) & ~tl->grant.privilege); 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; 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 goto err; // impossible
} }
} }
......
...@@ -5069,9 +5069,12 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables, ...@@ -5069,9 +5069,12 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
for (; i < number && tables != first_not_own_table && tables; for (; i < number && tables != first_not_own_table && tables;
tables= tables->next_global, i++) tables= tables->next_global, i++)
{ {
TABLE_LIST *const table_ref= tables->correspondent_table ?
tables->correspondent_table : tables;
ulong want_access= requirements; ulong want_access= requirements;
if (tables->security_ctx) if (table_ref->security_ctx)
sctx= tables->security_ctx; sctx= table_ref->security_ctx;
else else
sctx= backup_ctx; sctx= backup_ctx;
...@@ -5079,26 +5082,26 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables, ...@@ -5079,26 +5082,26 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
Register access for view underlying table. Register access for view underlying table.
Remove SHOW_VIEW_ACL, because it will be checked during making view 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; goto deny;
continue; continue;
} }
DBUG_PRINT("info", ("derived: %d view: %d", tables->derived != 0, DBUG_PRINT("info", ("derived: %d view: %d", table_ref->derived != 0,
tables->view != 0)); table_ref->view != 0));
if (tables->is_anonymous_derived_table() || if (table_ref->is_anonymous_derived_table() ||
(tables->table && tables->table->s && (table_ref->table && table_ref->table->s &&
(int)tables->table->s->tmp_table)) (int)table_ref->table->s->tmp_table))
continue; continue;
thd->security_ctx= sctx; thd->security_ctx= sctx;
if (check_access(thd, want_access, tables->get_db_name(), if (check_access(thd, want_access, table_ref->get_db_name(),
&tables->grant.privilege, &table_ref->grant.privilege,
&tables->grant.m_internal, &table_ref->grant.m_internal,
0, no_errors)) 0, no_errors))
goto deny; 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