diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/event_data_objects.cc | 16 | ||||
-rw-r--r-- | sql/event_db_repository.cc | 9 | ||||
-rw-r--r-- | sql/event_scheduler.cc | 7 | ||||
-rw-r--r-- | sql/events.cc | 16 | ||||
-rw-r--r-- | sql/sql_class.cc | 1 |
5 files changed, 46 insertions, 3 deletions
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 787b04c12c6..adac2b596c1 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -2017,6 +2017,7 @@ end_no_lex_start: ret= 1; else { + ulong saved_master_access; /* Peculiar initialization order is a crutch to avoid races in SHOW PROCESSLIST which reads thd->{query/query_length} without a mutex. @@ -2024,8 +2025,19 @@ end_no_lex_start: thd->query_length= 0; thd->query= sp_sql.c_ptr_safe(); thd->query_length= sp_sql.length(); - if (Events::drop_event(thd, dbname, name, FALSE)) - ret= 1; + + /* + NOTE: even if we run in read-only mode, we should be able to lock + the mysql.event table for writing. In order to achieve this, we + should call mysql_lock_tables() under the super-user. + */ + + saved_master_access= thd->security_ctx->master_access; + thd->security_ctx->master_access |= SUPER_ACL; + + ret= Events::drop_event(thd, dbname, name, FALSE); + + thd->security_ctx->master_access= saved_master_access; } } #ifndef NO_EMBEDDED_ACCESS_CHECKS diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 705bd8b2704..4451e763ff7 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -525,6 +525,10 @@ Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *tables, - whether this open mode would work under LOCK TABLES, or inside a stored function or trigger. + Note that if the table can't be locked successfully this operation will + close it. Therefore it provides guarantee that it either opens and locks + table or fails without leaving any tables open. + @param[in] thd Thread context @param[in] lock_type How to lock the table @param[out] table We will store the open table here @@ -544,7 +548,10 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type, tables.init_one_table("mysql", "event", lock_type); if (simple_open_n_lock_tables(thd, &tables)) + { + close_thread_tables(thd, FALSE, FALSE); DBUG_RETURN(TRUE); + } *table= tables.table; tables.table->use_all_columns(); @@ -995,6 +1002,8 @@ update_timing_fields_for_event(THD *thd, if (thd->current_stmt_binlog_row_based) thd->clear_current_stmt_binlog_row_based(); + DBUG_ASSERT(thd->security_ctx->master_access & SUPER_ACL); + if (open_event_table(thd, TL_WRITE, &table)) goto end; diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index b03b51f1134..d3a031fd8f8 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -399,6 +399,13 @@ Event_scheduler::start() new_thd->system_thread= SYSTEM_THREAD_EVENT_SCHEDULER; new_thd->command= COM_DAEMON; + /* + We should run the event scheduler thread under the super-user privileges. + In particular, this is needed to be able to lock the mysql.event table + for writing when the server is running in the read-only mode. + */ + new_thd->security_ctx->master_access |= SUPER_ACL; + scheduler_param_value= (struct scheduler_param *)my_malloc(sizeof(struct scheduler_param), MYF(0)); scheduler_param_value->thd= new_thd; diff --git a/sql/events.cc b/sql/events.cc index 5246bccc388..1bfbc5d6645 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -1124,11 +1124,25 @@ Events::load_events_from_db(THD *thd) READ_RECORD read_record_info; bool ret= TRUE; uint count= 0; + ulong saved_master_access; DBUG_ENTER("Events::load_events_from_db"); DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd)); - if (db_repository->open_event_table(thd, TL_WRITE, &table)) + /* + NOTE: even if we run in read-only mode, we should be able to lock the + mysql.event table for writing. In order to achieve this, we should call + mysql_lock_tables() under the super user. + */ + + saved_master_access= thd->security_ctx->master_access; + thd->security_ctx->master_access |= SUPER_ACL; + + ret= db_repository->open_event_table(thd, TL_WRITE, &table); + + thd->security_ctx->master_access= saved_master_access; + + if (ret) { sql_print_error("Event Scheduler: Failed to open table mysql.event"); DBUG_RETURN(TRUE); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ffbf0649961..d3ebfd94aa7 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2404,6 +2404,7 @@ void Security_context::init() host= user= priv_user= ip= 0; host_or_ip= "connecting host"; priv_host[0]= '\0'; + master_access= 0; #ifndef NO_EMBEDDED_ACCESS_CHECKS db_access= NO_ACCESS; #endif |