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.
This commit is contained in:
parent
49667f0441
commit
6fb2cdbc74
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user