summaryrefslogtreecommitdiff
path: root/sql/sql_parse.cc
diff options
context:
space:
mode:
authorKonstantin Osipov <kostja@sun.com>2010-02-03 16:43:03 +0300
committerKonstantin Osipov <kostja@sun.com>2010-02-03 16:43:03 +0300
commitc8555bdb35d998e99b6fb568f03c63479ff9272d (patch)
tree3b69ab5126c40ef71ad69a5bb469de82c4be90a0 /sql/sql_parse.cc
parent962d77de368e0cc90431e24d09e884f3760c7939 (diff)
parent3d915225611a921fad03934e58bf281b48fc15b0 (diff)
downloadmariadb-git-c8555bdb35d998e99b6fb568f03c63479ff9272d.tar.gz
Merge next-mr -> next-4284
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r--sql/sql_parse.cc392
1 files changed, 200 insertions, 192 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f139cdd6d73..6d7c0013365 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -346,15 +346,15 @@ bool is_log_table_write_query(enum enum_sql_command command)
}
void execute_init_command(THD *thd, LEX_STRING *init_command,
- rw_lock_t *var_lock)
+ mysql_rwlock_t *var_lock)
{
Vio* save_vio;
ulong save_client_capabilities;
- rw_rdlock(var_lock);
+ mysql_rwlock_rdlock(var_lock);
if (!init_command->length)
{
- rw_unlock(var_lock);
+ mysql_rwlock_unlock(var_lock);
return;
}
@@ -365,7 +365,7 @@ void execute_init_command(THD *thd, LEX_STRING *init_command,
*/
size_t len= init_command->length;
char *buf= thd->strmake(init_command->str, len);
- rw_unlock(var_lock);
+ mysql_rwlock_unlock(var_lock);
#if defined(ENABLED_PROFILING)
thd->profiling.start_new_query();
@@ -393,7 +393,7 @@ void execute_init_command(THD *thd, LEX_STRING *init_command,
static void handle_bootstrap_impl(THD *thd)
{
- FILE *file=bootstrap_file;
+ MYSQL_FILE *file= bootstrap_file;
char *buff;
const char* found_semicolon= NULL;
@@ -418,12 +418,12 @@ static void handle_bootstrap_impl(THD *thd)
buff= (char*) thd->net.buff;
thd->init_for_queries();
- while (fgets(buff, thd->net.max_packet, file))
+ while (mysql_file_fgets(buff, thd->net.max_packet, file))
{
- char *query, *res;
- /* strlen() can't be deleted because fgets() doesn't return length */
+ char *query;
+ /* strlen() can't be deleted because mysql_file_fgets() doesn't return length */
ulong length= (ulong) strlen(buff);
- while (buff[length-1] != '\n' && !feof(file))
+ while (buff[length-1] != '\n' && !mysql_file_feof(file))
{
/*
We got only a part of the current string. Will try to increase
@@ -437,7 +437,7 @@ static void handle_bootstrap_impl(THD *thd)
break;
}
buff= (char*) thd->net.buff;
- res= fgets(buff + length, thd->net.max_packet - length, file);
+ mysql_file_fgets(buff + length, thd->net.max_packet - length, file);
length+= (ulong) strlen(buff + length);
/* purecov: end */
}
@@ -499,6 +499,14 @@ pthread_handler_t handle_bootstrap(void *arg)
{
THD *thd=(THD*) arg;
+ mysql_thread_set_psi_id(thd->thread_id);
+
+ do_handle_bootstrap(thd);
+ return 0;
+}
+
+void do_handle_bootstrap(THD *thd)
+{
/* The following must be called before DBUG_ENTER */
thd->thread_stack= (char*) &thd;
if (my_thread_init() || thd->store_globals())
@@ -527,7 +535,7 @@ end:
pthread_exit(0);
#endif
- return 0;
+ return;
}
@@ -1105,8 +1113,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (lower_case_table_names)
my_casedn_str(files_charset_info, table_list.table_name);
- if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege,
- 0, 0, test(table_list.schema_table)))
+ if (check_access(thd, SELECT_ACL, table_list.db,
+ &table_list.grant.privilege,
+ &table_list.grant.m_internal,
+ 0, 0))
break;
if (check_grant(thd, SELECT_ACL, &table_list, TRUE, UINT_MAX, FALSE))
break;
@@ -2033,7 +2043,7 @@ mysql_execute_command(THD *thd)
privileges_requested,
all_tables, FALSE, UINT_MAX, FALSE);
else
- res= check_access(thd, privileges_requested, any_db, 0, 0, 0, 0);
+ res= check_access(thd, privileges_requested, any_db, NULL, NULL, 0, 0);
if (res)
break;
@@ -2173,8 +2183,9 @@ case SQLCOM_PREPARE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_access(thd, INDEX_ACL, first_table->db,
- &first_table->grant.privilege, 0, 0,
- test(first_table->schema_table)))
+ &first_table->grant.privilege,
+ &first_table->grant.m_internal,
+ 0, 0))
goto error;
res= mysql_assign_to_keycache(thd, first_table, &lex->ident);
break;
@@ -2183,8 +2194,9 @@ case SQLCOM_PREPARE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (check_access(thd, INDEX_ACL, first_table->db,
- &first_table->grant.privilege, 0, 0,
- test(first_table->schema_table)))
+ &first_table->grant.privilege,
+ &first_table->grant.m_internal,
+ 0, 0))
goto error;
res = mysql_preload_keys(thd, first_table);
break;
@@ -2194,9 +2206,9 @@ case SQLCOM_PREPARE:
{
if (check_global_access(thd, SUPER_ACL))
goto error;
- pthread_mutex_lock(&LOCK_active_mi);
+ mysql_mutex_lock(&LOCK_active_mi);
res = change_master(thd,active_mi);
- pthread_mutex_unlock(&LOCK_active_mi);
+ mysql_mutex_unlock(&LOCK_active_mi);
break;
}
case SQLCOM_SHOW_SLAVE_STAT:
@@ -2204,7 +2216,7 @@ case SQLCOM_PREPARE:
/* Accept one of two privileges */
if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
- pthread_mutex_lock(&LOCK_active_mi);
+ mysql_mutex_lock(&LOCK_active_mi);
if (active_mi != NULL)
{
res = show_master_info(thd, active_mi);
@@ -2215,7 +2227,7 @@ case SQLCOM_PREPARE:
WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO));
my_ok(thd);
}
- pthread_mutex_unlock(&LOCK_active_mi);
+ mysql_mutex_unlock(&LOCK_active_mi);
break;
}
case SQLCOM_SHOW_MASTER_STAT:
@@ -2522,9 +2534,9 @@ end_with_restore_list:
#ifdef HAVE_REPLICATION
case SQLCOM_SLAVE_START:
{
- pthread_mutex_lock(&LOCK_active_mi);
+ mysql_mutex_lock(&LOCK_active_mi);
start_slave(thd,active_mi,1 /* net report*/);
- pthread_mutex_unlock(&LOCK_active_mi);
+ mysql_mutex_unlock(&LOCK_active_mi);
break;
}
case SQLCOM_SLAVE_STOP:
@@ -2549,9 +2561,9 @@ end_with_restore_list:
goto error;
}
{
- pthread_mutex_lock(&LOCK_active_mi);
+ mysql_mutex_lock(&LOCK_active_mi);
stop_slave(thd,active_mi,1/* net report*/);
- pthread_mutex_unlock(&LOCK_active_mi);
+ mysql_mutex_unlock(&LOCK_active_mi);
break;
}
#endif /* HAVE_REPLICATION */
@@ -2582,10 +2594,13 @@ end_with_restore_list:
/* Must be set in the parser */
DBUG_ASSERT(select_lex->db);
if (check_access(thd, priv_needed, first_table->db,
- &first_table->grant.privilege, 0, 0,
- test(first_table->schema_table)) ||
- check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0,
- is_schema_db(select_lex->db))||
+ &first_table->grant.privilege,
+ &first_table->grant.m_internal,
+ 0, 0) ||
+ check_access(thd, INSERT_ACL | CREATE_ACL, select_lex->db,
+ &priv,
+ NULL, /* Do not use first_table->grant with select_lex->db */
+ 0, 0) ||
check_merge_table_access(thd, first_table->db,
(TABLE_LIST *)
create_info.merge_list.first))
@@ -2632,10 +2647,13 @@ end_with_restore_list:
for (table= first_table; table; table= table->next_local->next_local)
{
if (check_access(thd, ALTER_ACL | DROP_ACL, table->db,
- &table->grant.privilege,0,0, test(table->schema_table)) ||
- check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db,
- &table->next_local->grant.privilege, 0, 0,
- test(table->next_local->schema_table)))
+ &table->grant.privilege,
+ &table->grant.m_internal,
+ 0, 0) ||
+ check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db,
+ &table->next_local->grant.privilege,
+ &table->next_local->grant.m_internal,
+ 0, 0))
goto error;
TABLE_LIST old_list, new_list;
/*
@@ -2704,42 +2722,13 @@ end_with_restore_list:
}
else
{
- ulong save_priv;
-
- /*
- If it is an INFORMATION_SCHEMA table, SELECT_ACL privilege is the
- only privilege allowed. For any other privilege check_access()
- reports an error. That's how internal implementation protects
- INFORMATION_SCHEMA from updates.
-
- For ordinary tables any privilege from the SHOW_CREATE_TABLE_ACLS
- set is sufficient.
- */
-
- ulong check_privs= test(first_table->schema_table) ?
- SELECT_ACL : SHOW_CREATE_TABLE_ACLS;
-
- if (check_access(thd, check_privs, first_table->db,
- &save_priv, FALSE, FALSE,
- test(first_table->schema_table)))
- goto error;
-
/*
- save_priv contains any privileges actually granted by check_access
- (i.e. save_priv contains global (user- and database-level)
- privileges).
-
- The fact that check_access() returned FALSE does not mean that
- access is granted. We need to check if save_priv contains any
- table-specific privilege. If not, we need to check table-level
- privileges.
-
- If there are no global privileges and no table-level privileges,
- access is denied.
+ The fact that check_some_access() returned FALSE does not mean that
+ access is granted. We need to check if first_table->grant.privilege
+ contains any table-specific privilege.
*/
-
- if (!(save_priv & (SHOW_CREATE_TABLE_ACLS)) &&
- !has_any_table_level_privileges(thd, SHOW_CREATE_TABLE_ACLS, first_table))
+ if (check_some_access(thd, SHOW_CREATE_TABLE_ACLS, first_table) ||
+ (first_table->grant.privilege & SHOW_CREATE_TABLE_ACLS) == 0)
{
my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
"SHOW", thd->security_ctx->priv_user,
@@ -3201,7 +3190,7 @@ end_with_restore_list:
goto error;
#else
{
- if (check_access(thd, FILE_ACL, any_db,0,0,0,0))
+ if (check_access(thd, FILE_ACL, any_db, NULL, NULL, 0, 0))
goto error;
res= ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_LOGS);
break;
@@ -3388,8 +3377,7 @@ end_with_restore_list:
break;
}
#endif
- if (check_access(thd,CREATE_ACL,lex->name.str, 0, 1, 0,
- is_schema_db(lex->name.str)))
+ if (check_access(thd, CREATE_ACL, lex->name.str, NULL, NULL, 1, 0))
break;
if (thd->locked_tables_mode)
{
@@ -3424,8 +3412,7 @@ end_with_restore_list:
break;
}
#endif
- if (check_access(thd,DROP_ACL,lex->name.str,0,1,0,
- is_schema_db(lex->name.str)))
+ if (check_access(thd, DROP_ACL, lex->name.str, NULL, NULL, 1, 0))
break;
if (thd->locked_tables_mode)
{
@@ -3454,9 +3441,9 @@ end_with_restore_list:
my_error(ER_WRONG_DB_NAME, MYF(0), db->str);
break;
}
- if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, is_schema_db(db->str)) ||
- check_access(thd, DROP_ACL, db->str, 0, 1, 0, is_schema_db(db->str)) ||
- check_access(thd, CREATE_ACL, db->str, 0, 1, 0, is_schema_db(db->str)))
+ if (check_access(thd, ALTER_ACL, db->str, NULL, NULL, 1, 0) ||
+ check_access(thd, DROP_ACL, db->str, NULL, NULL, 1, 0) ||
+ check_access(thd, CREATE_ACL, db->str, NULL, NULL, 1, 0))
{
res= 1;
break;
@@ -3499,7 +3486,7 @@ end_with_restore_list:
break;
}
#endif
- if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, is_schema_db(db->str)))
+ if (check_access(thd, ALTER_ACL, db->str, NULL, NULL, 1, 0))
break;
if (thd->locked_tables_mode)
{
@@ -3584,7 +3571,7 @@ end_with_restore_list:
#endif
case SQLCOM_CREATE_FUNCTION: // UDF function
{
- if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
+ if (check_access(thd, INSERT_ACL, "mysql", NULL, NULL, 1, 0))
break;
#ifdef HAVE_DLOPEN
if (!(res = mysql_create_function(thd, &lex->udf)))
@@ -3598,7 +3585,7 @@ end_with_restore_list:
#ifndef NO_EMBEDDED_ACCESS_CHECKS
case SQLCOM_CREATE_USER:
{
- if (check_access(thd, INSERT_ACL, "mysql", 0, 1, 1, 0) &&
+ if (check_access(thd, INSERT_ACL, "mysql", NULL, NULL, 1, 1) &&
check_global_access(thd,CREATE_USER_ACL))
break;
/* Conditionally writes to binlog */
@@ -3608,7 +3595,7 @@ end_with_restore_list:
}
case SQLCOM_DROP_USER:
{
- if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 1, 0) &&
+ if (check_access(thd, DELETE_ACL, "mysql", NULL, NULL, 1, 1) &&
check_global_access(thd,CREATE_USER_ACL))
break;
/* Conditionally writes to binlog */
@@ -3618,7 +3605,7 @@ end_with_restore_list:
}
case SQLCOM_RENAME_USER:
{
- if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) &&
+ if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1) &&
check_global_access(thd,CREATE_USER_ACL))
break;
/* Conditionally writes to binlog */
@@ -3628,7 +3615,7 @@ end_with_restore_list:
}
case SQLCOM_REVOKE_ALL:
{
- if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) &&
+ if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1) &&
check_global_access(thd,CREATE_USER_ACL))
break;
/* Conditionally writes to binlog */
@@ -3640,11 +3627,10 @@ end_with_restore_list:
case SQLCOM_GRANT:
{
if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
- first_table ? first_table->db : select_lex->db,
- first_table ? &first_table->grant.privilege : 0,
- first_table ? 0 : 1, 0,
- first_table ? (bool) first_table->schema_table :
- select_lex->db ? is_schema_db(select_lex->db) : 0))
+ first_table ? first_table->db : select_lex->db,
+ first_table ? &first_table->grant.privilege : NULL,
+ first_table ? &first_table->grant.m_internal : NULL,
+ first_table ? 0 : 1, 0))
goto error;
if (thd->security_ctx->user) // If not replication
@@ -3671,7 +3657,7 @@ end_with_restore_list:
// TODO: use check_change_password()
if (is_acl_user(user->host.str, user->user.str) &&
user->password.str &&
- check_access(thd, UPDATE_ACL,"mysql",0,1,1,0))
+ check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1))
{
my_message(ER_PASSWORD_NOT_ALLOWED,
ER(ER_PASSWORD_NOT_ALLOWED), MYF(0));
@@ -3802,7 +3788,7 @@ end_with_restore_list:
goto error;
if ((thd->security_ctx->priv_user &&
!strcmp(thd->security_ctx->priv_user, grant_user->user.str)) ||
- !check_access(thd, SELECT_ACL, "mysql",0,1,0,0))
+ !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0))
{
res = mysql_show_grants(thd, grant_user);
}
@@ -3910,8 +3896,8 @@ end_with_restore_list:
goto create_sp_error;
}
- if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0,
- is_schema_db(lex->sphead->m_db.str)))
+ if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str,
+ NULL, NULL, 0, 0))
goto create_sp_error;
name= lex->sphead->name(&namelen);
@@ -4208,7 +4194,7 @@ create_sp_error:
lex->spname->m_name.length);
if (udf)
{
- if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0))
+ if (check_access(thd, DELETE_ACL, "mysql", NULL, NULL, 1, 0))
goto error;
if (!(res = mysql_drop_function(thd, &lex->spname->m_name)))
@@ -4608,8 +4594,9 @@ bool check_single_table_access(THD *thd, ulong privilege,
db_name= all_tables->db;
if (check_access(thd, privilege, db_name,
- &all_tables->grant.privilege, 0, no_errors,
- test(all_tables->schema_table)))
+ &all_tables->grant.privilege,
+ &all_tables->grant.m_internal,
+ 0, no_errors))
goto deny;
/* Show only 1 table for check_grant */
@@ -4675,17 +4662,17 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
@param want_access The requested access privileges.
@param db A pointer to the Db name.
@param[out] save_priv A pointer to the granted privileges will be stored.
+ @param grant_internal_info A pointer to the internal grant cache.
@param dont_check_global_grants True if no global grants are checked.
@param no_error True if no errors should be sent to the client.
- @param schema_db True if the db specified belongs to the meta data tables.
'save_priv' is used to save the User-table (global) and Db-table grants for
the supplied db name. Note that we don't store db level grants if the global
grants is enough to satisfy the request AND the global grants contains a
SELECT grant.
- A meta data table (from INFORMATION_SCHEMA) can always be accessed with
- a SELECT_ACL.
+ For internal databases (INFORMATION_SCHEMA, PERFORMANCE_SCHEMA),
+ additional rules apply, see ACL_internal_schema_access.
@see check_grant
@@ -4697,7 +4684,8 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
bool
check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
- bool dont_check_global_grants, bool no_errors, bool schema_db)
+ GRANT_INTERNAL_INFO *grant_internal_info,
+ bool dont_check_global_grants, bool no_errors)
{
Security_context *sctx= thd->security_ctx;
ulong db_access;
@@ -4720,7 +4708,10 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
if (save_priv)
*save_priv=0;
else
+ {
save_priv= &dummy;
+ dummy= 0;
+ }
thd_proc_info(thd, "checking permissions");
if ((!db || !db[0]) && !thd->db && !dont_check_global_grants)
@@ -4732,55 +4723,65 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
DBUG_RETURN(TRUE); /* purecov: tested */
}
- if (schema_db)
+ if ((db != NULL) && (db != any_db))
{
- /*
- We don't allow any simple privileges but SELECT_ACL or CREATE_VIEW_ACL
- on the information_schema database.
- */
- want_access &= ~SELECT_ACL;
- if (want_access & DB_ACLS)
+ const ACL_internal_schema_access *access;
+ access= get_cached_schema_access(grant_internal_info, db);
+ if (access)
{
- if (!no_errors)
+ switch (access->check(want_access, save_priv))
{
- const char *db_name= db ? db : thd->db;
- my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
- sctx->priv_user, sctx->priv_host, db_name);
+ case ACL_INTERNAL_ACCESS_GRANTED:
+ /*
+ All the privileges requested have been granted internally.
+ [out] *save_privileges= Internal privileges.
+ */
+ DBUG_RETURN(FALSE);
+ case ACL_INTERNAL_ACCESS_DENIED:
+ if (! no_errors)
+ {
+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
+ sctx->priv_user, sctx->priv_host, db);
+ }
+ DBUG_RETURN(TRUE);
+ case ACL_INTERNAL_ACCESS_CHECK_GRANT:
+ /*
+ Only some of the privilege requested have been granted internally,
+ proceed with the remaining bits of the request (want_access).
+ */
+ want_access&= ~(*save_priv);
+ break;
}
- /*
- Access denied;
- [out] *save_privileges= 0
- */
- DBUG_RETURN(TRUE);
- }
- else
- {
- /* Access granted */
- *save_priv= SELECT_ACL;
- DBUG_RETURN(FALSE);
}
}
if ((sctx->master_access & want_access) == want_access)
{
- /* get access for current db */
- db_access= sctx->db_access;
/*
1. If we don't have a global SELECT privilege, we have to get the
database specific access rights to be able to handle queries of type
UPDATE t1 SET a=1 WHERE b > 0
2. Change db access if it isn't current db which is being addressed
*/
- if (!(sctx->master_access & SELECT_ACL) &&
- (db && (!thd->db || db_is_pattern || strcmp(db,thd->db))))
- db_access=acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
- db_is_pattern);
-
- /*
- The effective privileges are the union of the global privileges
- and the the intersection of db- and host-privileges.
- */
- *save_priv=sctx->master_access | db_access;
+ if (!(sctx->master_access & SELECT_ACL))
+ {
+ if (db && (!thd->db || db_is_pattern || strcmp(db, thd->db)))
+ db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db,
+ db_is_pattern);
+ else
+ {
+ /* get access for current db */
+ db_access= sctx->db_access;
+ }
+ /*
+ The effective privileges are the union of the global privileges
+ and the intersection of db- and host-privileges,
+ plus the internal privileges.
+ */
+ *save_priv|= sctx->master_access | db_access;
+ }
+ else
+ *save_priv|= sctx->master_access;
DBUG_RETURN(FALSE);
}
if (((want_access & ~sctx->master_access) & ~DB_ACLS) ||
@@ -4816,10 +4817,10 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
/*
Save the union of User-table and the intersection between Db-table and
- Host-table privileges.
+ Host-table privileges, with the already saved internal privileges.
*/
db_access= (db_access | sctx->master_access);
- *save_priv= db_access;
+ *save_priv|= db_access;
/*
We need to investigate column- and table access if all requested privileges
@@ -4840,14 +4841,14 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
{
/*
Ok; but need to check table- and column privileges.
- [out] *save_privileges is (User-priv | (Db-priv & Host-priv))
+ [out] *save_privileges is (User-priv | (Db-priv & Host-priv) | Internal-priv)
*/
DBUG_RETURN(FALSE);
}
/*
Access is denied;
- [out] *save_privileges is (User-priv | (Db-priv & Host-priv))
+ [out] *save_privileges is (User-priv | (Db-priv & Host-priv) | Internal-priv)
*/
DBUG_PRINT("error",("Access denied"));
if (!no_errors)
@@ -4863,6 +4864,18 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
static bool check_show_access(THD *thd, TABLE_LIST *table)
{
+ /*
+ This is a SHOW command using an INFORMATION_SCHEMA table.
+ check_access() has not been called for 'table',
+ and SELECT is currently always granted on the I_S, so we automatically
+ grant SELECT on table here, to bypass a call to check_access().
+ Note that not calling check_access(table) is an optimization,
+ which needs to be revisited if the INFORMATION_SCHEMA does
+ not always automatically grant SELECT but use the grant tables.
+ See Bug#38837 need a way to disable information_schema for security
+ */
+ table->grant.privilege= SELECT_ACL;
+
switch (get_schema_table_idx(table->schema_table)) {
case SCH_SCHEMATA:
return (specialflag & SPECIAL_SKIP_SHOW_DB) &&
@@ -4879,8 +4892,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
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)))
+ &thd->col_access, NULL, FALSE, FALSE))
return TRUE;
if (!thd->col_access && check_grant_db(thd, dst_db_name))
@@ -4904,8 +4916,9 @@ static bool check_show_access(THD *thd, TABLE_LIST *table)
DBUG_ASSERT(dst_table);
if (check_access(thd, SELECT_ACL, dst_table->db,
- &dst_table->grant.privilege, FALSE, FALSE,
- test(dst_table->schema_table)))
+ &dst_table->grant.privilege,
+ &dst_table->grant.m_internal,
+ FALSE, FALSE))
return TRUE; /* Access denied */
/*
@@ -4986,23 +4999,6 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
sctx= backup_ctx;
/*
- Always allow SELECT on schema tables. This is done by removing the
- required SELECT_ACL privilege in the want_access parameter.
- Disallow any other DDL or DML operation on any schema table.
- */
- if (tables->schema_table)
- {
- want_access &= ~SELECT_ACL;
- if (want_access & DB_ACLS)
- {
- if (!no_errors)
- my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
- sctx->priv_user, sctx->priv_host,
- INFORMATION_SCHEMA_NAME.str);
- goto deny;
- }
- }
- /*
Register access for view underlying table.
Remove SHOW_VIEW_ACL, because it will be checked during making view
*/
@@ -5022,18 +5018,11 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
(int)tables->table->s->tmp_table))
continue;
thd->security_ctx= sctx;
- if ((sctx->master_access & want_access) == want_access &&
- thd->db)
- tables->grant.privilege= want_access;
- else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0)
- {
- if (check_access(thd, want_access, tables->get_db_name(),
- &tables->grant.privilege, 0, no_errors,
- test(tables->schema_table)))
- goto deny; // Access denied
- }
- else if (check_access(thd, want_access, tables->get_db_name(),
- &tables->grant.privilege, 0, no_errors, 0))
+
+ if (check_access(thd, want_access, tables->get_db_name(),
+ &tables->grant.privilege,
+ &tables->grant.m_internal,
+ 0, no_errors))
goto deny;
}
thd->security_ctx= backup_ctx;
@@ -5061,11 +5050,20 @@ check_routine_access(THD *thd, ulong want_access,char *db, char *name,
calculating db_access) under the assumption that it's common to
give persons global right to execute all stored SP (but not
necessary to create them).
+ Note that this effectively bypasses the ACL_internal_schema_access checks
+ that are implemented for the INFORMATION_SCHEMA and PERFORMANCE_SCHEMA,
+ which are located in check_access().
+ Since the I_S and P_S do not contain routines, this bypass is ok,
+ as long as this code path is not abused to create routines.
+ The assert enforce that.
*/
+ DBUG_ASSERT((want_access & CREATE_PROC_ACL) == 0);
if ((thd->security_ctx->master_access & want_access) == want_access)
tables->grant.privilege= want_access;
- else if (check_access(thd,want_access,db,&tables->grant.privilege,
- 0, no_errors, 0))
+ else if (check_access(thd, want_access, db,
+ &tables->grant.privilege,
+ &tables->grant.m_internal,
+ 0, no_errors))
return TRUE;
return check_grant_routine(thd, want_access, tables, is_proc, no_errors);
@@ -5089,13 +5087,18 @@ bool check_some_routine_access(THD *thd, const char *db, const char *name,
bool is_proc)
{
ulong save_priv;
- if (thd->security_ctx->master_access & SHOW_PROC_ACLS)
- return FALSE;
/*
- There are no routines in information_schema db. So we can safely
- pass zero to last paramter of check_access function
+ The following test is just a shortcut for check_access() (to avoid
+ calculating db_access)
+ Note that this effectively bypasses the ACL_internal_schema_access checks
+ that are implemented for the INFORMATION_SCHEMA and PERFORMANCE_SCHEMA,
+ which are located in check_access().
+ Since the I_S and P_S do not contain routines, this bypass is ok,
+ as it only opens SHOW_PROC_ACLS.
*/
- if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, 0, 1, 0) ||
+ if (thd->security_ctx->master_access & SHOW_PROC_ACLS)
+ return FALSE;
+ if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, NULL, 0, 1) ||
(save_priv & SHOW_PROC_ACLS))
return FALSE;
return check_routine_level_acl(thd, db, name, is_proc);
@@ -5125,8 +5128,9 @@ bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table)
if (access & want_access)
{
if (!check_access(thd, access, table->db,
- &table->grant.privilege, 0, 1,
- test(table->schema_table)) &&
+ &table->grant.privilege,
+ &table->grant.m_internal,
+ 0, 1) &&
!check_grant(thd, access, table, FALSE, 1, TRUE))
DBUG_RETURN(0);
}
@@ -6468,9 +6472,9 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
}
#ifdef HAVE_REPLICATION
- pthread_mutex_lock(&LOCK_active_mi);
+ mysql_mutex_lock(&LOCK_active_mi);
rotate_relay_log(active_mi);
- pthread_mutex_unlock(&LOCK_active_mi);
+ mysql_mutex_unlock(&LOCK_active_mi);
#endif
/* flush slow and general logs */
@@ -6598,10 +6602,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
if (options & REFRESH_SLAVE)
{
tmp_write_to_binlog= 0;
- pthread_mutex_lock(&LOCK_active_mi);
+ mysql_mutex_lock(&LOCK_active_mi);
if (reset_slave(thd, active_mi))
result=1;
- pthread_mutex_unlock(&LOCK_active_mi);
+ mysql_mutex_unlock(&LOCK_active_mi);
}
#endif
if (options & REFRESH_USER_RESOURCES)
@@ -6636,7 +6640,7 @@ uint kill_one_thread(THD *thd, ulong id, bool only_kill_query)
continue;
if (tmp->thread_id == id)
{
- pthread_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
+ mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
break;
}
}
@@ -6669,7 +6673,7 @@ uint kill_one_thread(THD *thd, ulong id, bool only_kill_query)
}
else
error=ER_KILL_DENIED_ERROR;
- pthread_mutex_unlock(&tmp->LOCK_thd_data);
+ mysql_mutex_unlock(&tmp->LOCK_thd_data);
}
DBUG_PRINT("exit", ("%d", error));
DBUG_RETURN(error);
@@ -6850,12 +6854,14 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
if (table->derived)
table->grant.privilege= SELECT_ACL;
else if ((check_access(thd, UPDATE_ACL, table->db,
- &table->grant.privilege, 0, 1,
- test(table->schema_table)) ||
+ &table->grant.privilege,
+ &table->grant.m_internal,
+ 0, 1) ||
check_grant(thd, UPDATE_ACL, table, FALSE, 1, TRUE)) &&
(check_access(thd, SELECT_ACL, table->db,
- &table->grant.privilege, 0, 0,
- test(table->schema_table)) ||
+ &table->grant.privilege,
+ &table->grant.m_internal,
+ 0, 0) ||
check_grant(thd, SELECT_ACL, table, FALSE, 1, FALSE)))
DBUG_RETURN(TRUE);
@@ -6872,8 +6878,9 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
if (!table->table_in_first_from_clause)
{
if (check_access(thd, SELECT_ACL, table->db,
- &table->grant.privilege, 0, 0,
- test(table->schema_table)) ||
+ &table->grant.privilege,
+ &table->grant.m_internal,
+ 0, 0) ||
check_grant(thd, SELECT_ACL, table, FALSE, 1, FALSE))
DBUG_RETURN(TRUE);
}
@@ -7182,8 +7189,9 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
(select_lex->item_list.elements ? INSERT_ACL : 0);
if (check_access(thd, want_priv, create_table->db,
- &create_table->grant.privilege, 0, 0,
- test(create_table->schema_table)) ||
+ &create_table->grant.privilege,
+ &create_table->grant.m_internal,
+ 0, 0) ||
check_merge_table_access(thd, create_table->db,
(TABLE_LIST *)
lex->create_info.merge_list.first))