mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
Fix for BUG#27337: Privileges are not properly restored.
The problem was that THD::db_access variable was not restored after database switch in stored-routine-execution code. The fix is to restore THD::db_access in this case. Unfortunately, this fix requires additional changes, because in prepare_schema_table(), called on the parsing stage, we checked privileges. That was wrong according to our design, but this flaw haven't struck so far, because it was masked. All privilege checkings must be done on the execution stage in order to be compatible with prepared statements and stored routines. So, this patch also contains patch for prepare_schema_table(), which moves the checkings to the execution phase. mysql-test/r/grant.result: Updated result file. mysql-test/t/grant.test: Added test case for BUG#27337. sql/mysql_priv.h: Added function declaration. sql/sql_db.cc: Fix for BUG#27337 -- set THD::db_access even if we're called from stored-routine-execution code. sql/sql_parse.cc: Split prepare_schema_table() into two functions: - prepare_schema_table(), which is called from the parser (parsing stage); - check_show_access(), which is called on the execution stage. sql/sql_show.cc: Ignore schema_select_lex member if its table is NULL.
This commit is contained in:
167
sql/sql_parse.cc
167
sql/sql_parse.cc
@ -2237,7 +2237,8 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
|
||||
enum enum_schema_tables schema_table_idx)
|
||||
{
|
||||
DBUG_ENTER("prepare_schema_table");
|
||||
SELECT_LEX *sel= 0;
|
||||
SELECT_LEX *schema_select_lex= NULL;
|
||||
|
||||
switch (schema_table_idx) {
|
||||
case SCH_SCHEMATA:
|
||||
#if defined(DONT_ALLOW_SHOW_COMMANDS)
|
||||
@ -2245,11 +2246,9 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
|
||||
ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
|
||||
DBUG_RETURN(1);
|
||||
#else
|
||||
if ((specialflag & SPECIAL_SKIP_SHOW_DB) &&
|
||||
check_global_access(thd, SHOW_DB_ACL))
|
||||
DBUG_RETURN(1);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SCH_TABLE_NAMES:
|
||||
case SCH_TABLES:
|
||||
case SCH_VIEWS:
|
||||
@ -2259,32 +2258,25 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
|
||||
ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
|
||||
DBUG_RETURN(1);
|
||||
#else
|
||||
if (lex->select_lex.db == NULL &&
|
||||
thd->copy_db_to(&lex->select_lex.db, NULL))
|
||||
{
|
||||
char *db;
|
||||
if (lex->select_lex.db == NULL &&
|
||||
thd->copy_db_to(&lex->select_lex.db, 0))
|
||||
{
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
db= lex->select_lex.db;
|
||||
remove_escape(db); // Fix escaped '_'
|
||||
if (check_db_name(db))
|
||||
{
|
||||
my_error(ER_WRONG_DB_NAME, MYF(0), db);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (check_access(thd, SELECT_ACL, db, &thd->col_access, 0, 0,
|
||||
is_schema_db(db)))
|
||||
DBUG_RETURN(1); /* purecov: inspected */
|
||||
if (!thd->col_access && check_grant_db(thd,db))
|
||||
{
|
||||
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
|
||||
thd->security_ctx->priv_user, thd->security_ctx->priv_host,
|
||||
db);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
break;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
schema_select_lex= new SELECT_LEX();
|
||||
schema_select_lex->db= lex->select_lex.db;
|
||||
schema_select_lex->table_list.first= NULL;
|
||||
remove_escape(schema_select_lex->db); // Fix escaped '_'
|
||||
|
||||
if (check_db_name(schema_select_lex->db))
|
||||
{
|
||||
my_error(ER_WRONG_DB_NAME, MYF(0), schema_select_lex->db);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
#endif
|
||||
case SCH_COLUMNS:
|
||||
case SCH_STATISTICS:
|
||||
@ -2293,28 +2285,23 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
|
||||
ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
|
||||
DBUG_RETURN(1);
|
||||
#else
|
||||
if (table_ident)
|
||||
{
|
||||
DBUG_ASSERT(table_ident);
|
||||
|
||||
TABLE_LIST **query_tables_last= lex->query_tables_last;
|
||||
sel= new SELECT_LEX();
|
||||
schema_select_lex= new SELECT_LEX();
|
||||
/* 'parent_lex' is used in init_query() so it must be before it. */
|
||||
sel->parent_lex= lex;
|
||||
sel->init_query();
|
||||
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
|
||||
(List<String> *) 0, (List<String> *) 0))
|
||||
schema_select_lex->parent_lex= lex;
|
||||
schema_select_lex->init_query();
|
||||
if (!schema_select_lex->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
|
||||
(List<String> *) 0, (List<String> *) 0))
|
||||
DBUG_RETURN(1);
|
||||
lex->query_tables_last= query_tables_last;
|
||||
TABLE_LIST *table_list= (TABLE_LIST*) sel->table_list.first;
|
||||
char *db= table_list->db;
|
||||
remove_escape(db); // Fix escaped '_'
|
||||
remove_escape(table_list->table_name);
|
||||
if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,
|
||||
&table_list->grant.privilege, 0, 0,
|
||||
test(table_list->schema_table)))
|
||||
DBUG_RETURN(1); /* purecov: inspected */
|
||||
if (grant_option && check_grant(thd, SELECT_ACL, table_list, 2,
|
||||
UINT_MAX, 0))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
TABLE_LIST *dst_table= (TABLE_LIST*) schema_select_lex->table_list.first;
|
||||
remove_escape(dst_table->db); // Fix escaped '_'
|
||||
remove_escape(dst_table->table_name);
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -2341,7 +2328,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first;
|
||||
table_list->schema_select_lex= sel;
|
||||
table_list->schema_select_lex= schema_select_lex;
|
||||
table_list->schema_table_reformed= 1;
|
||||
statistic_increment(thd->status_var.com_stat[lex->orig_sql_command],
|
||||
&LOCK_status);
|
||||
@ -5390,6 +5377,83 @@ bool check_global_access(THD *thd, ulong want_access)
|
||||
}
|
||||
|
||||
|
||||
static bool check_show_access(THD *thd, TABLE_LIST *table)
|
||||
{
|
||||
switch (get_schema_table_idx(table->schema_table))
|
||||
{
|
||||
case SCH_SCHEMATA:
|
||||
return (specialflag & SPECIAL_SKIP_SHOW_DB) &&
|
||||
check_global_access(thd, SHOW_DB_ACL);
|
||||
|
||||
case SCH_TABLE_NAMES:
|
||||
case SCH_TABLES:
|
||||
case SCH_VIEWS:
|
||||
case SCH_TRIGGERS:
|
||||
{
|
||||
const char *dst_db_name= table->schema_select_lex->db;
|
||||
|
||||
DBUG_ASSERT(dst_db_name);
|
||||
|
||||
if (check_access(thd, SELECT_ACL, dst_db_name,
|
||||
&thd->col_access, FALSE, FALSE,
|
||||
is_schema_db(dst_db_name)))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!thd->col_access && check_grant_db(thd, dst_db_name))
|
||||
{
|
||||
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
|
||||
thd->security_ctx->priv_user,
|
||||
thd->security_ctx->priv_host,
|
||||
dst_db_name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
case SCH_COLUMNS:
|
||||
case SCH_STATISTICS:
|
||||
{
|
||||
TABLE_LIST *dst_table=
|
||||
(TABLE_LIST *) table->schema_select_lex->table_list.first;
|
||||
|
||||
DBUG_ASSERT(dst_table);
|
||||
|
||||
if (check_access(thd, SELECT_ACL | EXTRA_ACL,
|
||||
dst_table->db,
|
||||
&dst_table->grant.privilege,
|
||||
FALSE, FALSE,
|
||||
test(dst_table->schema_table)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return grant_option &&
|
||||
check_grant(thd, SELECT_ACL, dst_table, 2, UINT_MAX, FALSE);
|
||||
}
|
||||
|
||||
case SCH_OPEN_TABLES:
|
||||
case SCH_VARIABLES:
|
||||
case SCH_STATUS:
|
||||
case SCH_PROCEDURES:
|
||||
case SCH_CHARSETS:
|
||||
case SCH_COLLATIONS:
|
||||
case SCH_COLLATION_CHARACTER_SET_APPLICABILITY:
|
||||
case SCH_USER_PRIVILEGES:
|
||||
case SCH_SCHEMA_PRIVILEGES:
|
||||
case SCH_TABLE_PRIVILEGES:
|
||||
case SCH_COLUMN_PRIVILEGES:
|
||||
case SCH_TABLE_CONSTRAINTS:
|
||||
case SCH_KEY_COLUMN_USAGE:
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check the privilege for all used tables.
|
||||
|
||||
@ -5450,7 +5514,16 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
|
||||
Remove SHOW_VIEW_ACL, because it will be checked during making view
|
||||
*/
|
||||
tables->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
|
||||
if (tables->derived || tables->schema_table ||
|
||||
|
||||
if (tables->schema_table_reformed)
|
||||
{
|
||||
if (check_show_access(thd, tables))
|
||||
goto deny;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tables->derived ||
|
||||
(tables->table && (int)tables->table->s->tmp_table) ||
|
||||
my_tz_check_n_skip_implicit_tables(&tables,
|
||||
thd->lex->time_zone_tables_used))
|
||||
|
Reference in New Issue
Block a user