summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <andrey@lmy004.>2006-02-14 19:44:10 +0100
committerunknown <andrey@lmy004.>2006-02-14 19:44:10 +0100
commit1161b5213d454b3e4bca697a52b6df6222696151 (patch)
tree3739d8cbd248e3dbf9879c92f2e735c4ea3a0fc7
parent7b9223fcc1521500461dfc7a35caec632f3d1eaa (diff)
parentb07392692cef6532a83a0f4a6f552842c759c144 (diff)
downloadmariadb-git-1161b5213d454b3e4bca697a52b6df6222696151.tar.gz
Merge ahristov@bk-internal.mysql.com:/home/bk/mysql-5.1-new
into lmy004.:/work/mysql-5.1-bug17289 mysql-test/r/events.result: Auto merged mysql-test/t/events.test: Auto merged sql/event.h: Auto merged sql/event_executor.cc: Auto merged sql/event_timed.cc: Auto merged
-rw-r--r--mysql-test/r/events.result27
-rw-r--r--mysql-test/t/events.test33
-rw-r--r--sql/event.h6
-rw-r--r--sql/event_executor.cc101
-rw-r--r--sql/event_timed.cc84
-rw-r--r--sql/sql_error.cc13
6 files changed, 233 insertions, 31 deletions
diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result
index 851e9c84810..5dd11895f65 100644
--- a/mysql-test/r/events.result
+++ b/mysql-test/r/events.result
@@ -1,5 +1,28 @@
create database if not exists events_test;
use events_test;
+CREATE USER pauline@localhost;
+CREATE DATABASE db_x;
+GRANT EVENT ON db_x.* TO pauline@localhost;
+USE db_x;
+CREATE TABLE x_table(a int);
+CREATE EVENT e_x1 ON SCHEDULE EVERY 1 SECOND DO DROP DATABASE db_x;
+CREATE EVENT e_x2 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE x_table;
+SHOW DATABASES LIKE 'db_x';
+Database (db_x)
+db_x
+SET GLOBAL event_scheduler=1;
+SHOW DATABASES LIKE 'db_x';
+Database (db_x)
+db_x
+SHOW TABLES FROM db_x;
+Tables_in_db_x
+x_table
+SET GLOBAL event_scheduler=0;
+DROP EVENT e_x1;
+DROP EVENT e_x2;
+DROP DATABASE db_x;
+DROP USER pauline@localhost;
+USE events_test;
drop event if exists event1;
Warnings:
Note 1305 Event event1 does not exist
@@ -331,7 +354,7 @@ show processlist;
Id User Host db Command Time State Info
# root localhost events_test Query # NULL show processlist
# event_scheduler NULL Connect # Sleeping NULL
-# root events_test Connect # User lock select get_lock("test_lock2", 20)
+# root localhost events_test Connect # User lock select get_lock("test_lock2", 20)
"Release the mutex, the event worker should finish."
select release_lock("test_lock2");
release_lock("test_lock2")
@@ -349,6 +372,8 @@ set global event_scheduler=0;
show processlist;
Id User Host db Command Time State Info
# root localhost events_test Query # NULL show processlist
+# event_scheduler NULL Connect # Sleeping NULL
+# root localhost events_test Connect # User lock select get_lock("test_lock2_1", 20)
"Release the lock so the child process should finish. Hence the scheduler also"
select release_lock("test_lock2_1");
release_lock("test_lock2_1")
diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test
index 1c0c897c0fd..9c084bc6522 100644
--- a/mysql-test/t/events.test
+++ b/mysql-test/t/events.test
@@ -1,5 +1,38 @@
create database if not exists events_test;
use events_test;
+
+#
+# START: BUG #17289 Events: missing privilege check for drop database
+#
+CREATE USER pauline@localhost;
+CREATE DATABASE db_x;
+GRANT EVENT ON db_x.* TO pauline@localhost;
+USE db_x;
+CREATE TABLE x_table(a int);
+connect (priv_conn,localhost,pauline,,db_x);
+CREATE EVENT e_x1 ON SCHEDULE EVERY 1 SECOND DO DROP DATABASE db_x;
+CREATE EVENT e_x2 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE x_table;
+connection default;
+SHOW DATABASES LIKE 'db_x';
+SET GLOBAL event_scheduler=1;
+--sleep 2
+SHOW DATABASES LIKE 'db_x';
+SHOW TABLES FROM db_x;
+SET GLOBAL event_scheduler=0;
+--sleep 1
+connection priv_conn;
+DROP EVENT e_x1;
+DROP EVENT e_x2;
+disconnect priv_conn;
+connection default;
+DROP DATABASE db_x;
+DROP USER pauline@localhost;
+USE events_test;
+--sleep 1
+#
+# END: BUG #17289 Events: missing privilege check for drop database
+#
+
drop event if exists event1;
create event event1 on schedule every 15 minute starts now() ends date_add(now(), interval 5 hour) DO begin end;
alter event event1 rename to event2 enable;
diff --git a/sql/event.h b/sql/event.h
index 27abccf5b89..e459914326b 100644
--- a/sql/event.h
+++ b/sql/event.h
@@ -205,6 +205,12 @@ public:
delete sphead;
sphead= 0;
}
+protected:
+ bool
+ change_security_context(THD *thd, Security_context **backup);
+
+ void
+ restore_security_context(THD *thd, Security_context *backup);
};
diff --git a/sql/event_executor.cc b/sql/event_executor.cc
index 897c782cfee..43350dcded3 100644
--- a/sql/event_executor.cc
+++ b/sql/event_executor.cc
@@ -49,7 +49,8 @@ static uint workers_count;
static int
evex_load_events_from_db(THD *thd);
-
+bool
+evex_print_warnings(THD *thd, event_timed *et);
/*
TODO Andrey: Check for command line option whether to start
@@ -258,7 +259,8 @@ init_event_thread(THD* thd)
{
DBUG_ENTER("init_event_thread");
thd->client_capabilities= 0;
- thd->security_ctx->skip_grants();
+ thd->security_ctx->master_access= 0;
+ thd->security_ctx->db_access= 0;
thd->security_ctx->host= (char*)my_localhost;
my_net_init(&thd->net, 0);
thd->net.read_timeout = slave_net_timeout;
@@ -343,8 +345,11 @@ event_executor_main(void *arg)
if (init_event_thread(thd))
goto err;
-
- // make this thread invisible it has no vio -> show processlist won't see
+
+ /*
+ make this thread visible it has no vio -> show processlist won't see it
+ unless it's marked as system thread
+ */
thd->system_thread= 1;
VOID(pthread_mutex_lock(&LOCK_thread_count));
@@ -629,21 +634,8 @@ event_executor_worker(void *event_void)
thd= current_thd;
#endif
- // thd->security_ctx->priv_host is char[MAX_HOSTNAME]
-
- strxnmov(thd->security_ctx->priv_host, sizeof(thd->security_ctx->priv_host),
- event->definer_host.str, NullS);
-
- thd->security_ctx->user= thd->security_ctx->priv_user=
- my_strdup(event->definer_user.str, MYF(0));
-
- thd->db= event->dbname.str;
- if (!check_access(thd, EVENT_ACL, event->dbname.str, 0, 0, 0,
- is_schema_db(event->dbname.str)))
{
int ret;
- DBUG_PRINT("info", (" EVEX EXECUTING event %s.%s [EXPR:%d]",
- event->dbname.str, event->name.str,(int) event->expression));
sql_print_information(" EVEX EXECUTING event %s.%s [EXPR:%d]",
event->dbname.str, event->name.str,(int) event->expression);
@@ -655,10 +647,7 @@ event_executor_worker(void *event_void)
if (ret == EVEX_COMPILE_ERROR)
sql_print_information(" EVEX COMPILE ERROR for event %s.%s",
event->dbname.str, event->name.str);
-
- DBUG_PRINT("info", (" EVEX EXECUTED event %s.%s [EXPR:%d]. RetCode=%d",
- event->dbname.str, event->name.str,
- (int) event->expression, ret));
+ evex_print_warnings(thd, event);
}
if ((event->flags & EVENT_EXEC_NO_MORE) || event->status==MYSQL_EVENT_DISABLED)
{
@@ -669,7 +658,6 @@ event_executor_worker(void *event_void)
delete event;
}
- thd->db= 0;
err:
VOID(pthread_mutex_lock(&LOCK_thread_count));
@@ -847,3 +835,72 @@ sys_var_event_executor::update(THD *thd, set_var *var)
DBUG_RETURN(0);
}
+extern LEX_STRING warning_level_names[];
+
+typedef void (*sql_print_xxx_func)(const char *format, ...);
+static sql_print_xxx_func sql_print_xxx_handlers[3] =
+{
+ sql_print_information,
+ sql_print_warning,
+ sql_print_error
+};
+
+/*
+ Prints the stack of infos, warnings, errors from thd to
+ the console so it can be fetched by the logs-into-tables and
+ checked later.
+
+ Synopsis
+ evex_print_warnings
+ thd - thread used during the execution of the event
+ et - the event itself
+
+ Returns
+ 0 - OK (always)
+
+*/
+
+bool
+evex_print_warnings(THD *thd, event_timed *et)
+{
+ MYSQL_ERROR *err;
+ DBUG_ENTER("evex_show_warnings");
+ char msg_buf[1024];
+ char prefix_buf[512];
+ String prefix(prefix_buf, sizeof(prefix_buf), system_charset_info);
+ prefix.length(0);
+
+ List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ while ((err= it++))
+ {
+ String err_msg(msg_buf, sizeof(msg_buf), system_charset_info);
+ err_msg.length(0);// set it to 0 or we start adding at the end
+ if (!prefix.length())
+ {
+ prefix.append("SCHEDULER: [");
+
+ append_identifier(thd,&prefix,et->definer_user.str,et->definer_user.length);
+ prefix.append('@');
+ append_identifier(thd,&prefix,et->definer_host.str,et->definer_host.length);
+ prefix.append("][", 2);
+ append_identifier(thd,&prefix, et->dbname.str, et->dbname.length);
+ prefix.append('.');
+ append_identifier(thd,&prefix, et->name.str, et->name.length);
+ prefix.append("] ", 2);
+ }
+
+ err_msg.append(prefix);
+ err_msg.append('[');
+ err_msg.append(warning_level_names[err->level].str,
+ warning_level_names[err->level].length, system_charset_info);
+ err_msg.append("] [");
+ err_msg.append(err->msg, strlen(err->msg), system_charset_info);
+ err_msg.append("]");
+ DBUG_ASSERT(err->level < 3);
+ (sql_print_xxx_handlers[err->level])("%*s", err_msg.length(), err_msg.c_ptr());
+// sql_print_information("%*s", err_msg.length(), err_msg.c_ptr());
+ }
+
+
+ DBUG_RETURN(FALSE);
+}
diff --git a/sql/event_timed.cc b/sql/event_timed.cc
index 068c98bd410..e32e3fe4949 100644
--- a/sql/event_timed.cc
+++ b/sql/event_timed.cc
@@ -1051,12 +1051,13 @@ event_timed::get_create_event(THD *thd, String *buf)
Executes the event (the underlying sp_head object);
SYNOPSIS
- evex_fill_row()
+ event_timed::execute()
thd THD
mem_root If != NULL use it to compile the event on it
Returns
0 - success
+ -99 - No access to the database.
-100 - event in execution (parallel execution is impossible)
others - retcodes of sp_head::execute_procedure()
@@ -1065,10 +1066,12 @@ event_timed::get_create_event(THD *thd, String *buf)
int
event_timed::execute(THD *thd, MEM_ROOT *mem_root)
{
- List<Item> empty_item_list;
+ Security_context *save_ctx;
int ret= 0;
DBUG_ENTER("event_timed::execute");
+ DBUG_PRINT("info", (" EVEX EXECUTING event %s.%s [EXPR:%d]",
+ dbname.str, name.str, (int) expression));
VOID(pthread_mutex_lock(&this->LOCK_running));
if (running)
@@ -1080,12 +1083,35 @@ event_timed::execute(THD *thd, MEM_ROOT *mem_root)
VOID(pthread_mutex_unlock(&this->LOCK_running));
// TODO Andrey : make this as member variable and delete in destructor
- empty_item_list.empty();
if (!sphead && (ret= compile(thd, mem_root)))
goto done;
- ret= sphead->execute_procedure(thd, &empty_item_list);
+ thd->db= dbname.str;
+ thd->db_length= dbname.length;
+
+ DBUG_PRINT("info", ("master_access=%d db_access=%d",
+ thd->security_ctx->master_access, thd->security_ctx->db_access));
+ change_security_context(thd, &save_ctx);
+ DBUG_PRINT("info", ("master_access=%d db_access=%d",
+ thd->security_ctx->master_access, thd->security_ctx->db_access));
+// if (mysql_change_db(thd, dbname.str, 0))
+ if (!check_access(thd, EVENT_ACL,dbname.str, 0, 0, 0,is_schema_db(dbname.str)))
+ {
+ List<Item> empty_item_list;
+ empty_item_list.empty();
+ ret= sphead->execute_procedure(thd, &empty_item_list);
+ }
+ else
+ {
+ DBUG_PRINT("error", ("%s@%s has no rights on %s", definer_user.str,
+ definer_host.str, dbname.str));
+ ret= -99;
+ }
+ restore_security_context(thd, save_ctx);
+ DBUG_PRINT("info", ("master_access=%d db_access=%d",
+ thd->security_ctx->master_access, thd->security_ctx->db_access));
+ thd->db= 0;
VOID(pthread_mutex_lock(&this->LOCK_running));
running= false;
@@ -1098,12 +1124,62 @@ done:
delete sphead;
sphead= 0;
}
+ DBUG_PRINT("info", (" EVEX EXECUTED event %s.%s [EXPR:%d]. RetCode=%d",
+ dbname.str, name.str, (int) expression, ret));
DBUG_RETURN(ret);
}
/*
+ Switches the security context
+ Synopsis
+ event_timed::change_security_context()
+ thd - thread
+ backup - where to store the old context
+
+ RETURN
+ 0 - OK
+ 1 - Error (generates error too)
+*/
+bool
+event_timed::change_security_context(THD *thd, Security_context **backup)
+{
+ DBUG_ENTER("event_timed::change_security_context");
+ DBUG_PRINT("info",("%s@%s@%s",definer_user.str,definer_host.str, dbname.str));
+ *backup= 0;
+ if (acl_getroot_no_password(&sphead->m_security_ctx, definer_user.str,
+ definer_host.str, definer_host.str, dbname.str))
+ {
+ my_error(ER_NO_SUCH_USER, MYF(0), definer_user.str, definer_host.str);
+ DBUG_RETURN(TRUE);
+ }
+ *backup= thd->security_ctx;
+ thd->security_ctx= &sphead->m_security_ctx;
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/*
+ Restores the security context
+ Synopsis
+ event_timed::restore_security_context()
+ thd - thread
+ backup - switch to this context
+ */
+
+void
+event_timed::restore_security_context(THD *thd, Security_context *backup)
+{
+ DBUG_ENTER("event_timed::change_security_context");
+ if (backup)
+ thd->security_ctx= backup;
+ DBUG_VOID_RETURN;
+}
+
+
+/*
Compiles an event before it's execution. Compiles the anonymous
sp_head object held by the event
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index 191a6e0a1fd..74df3b68a0d 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -211,8 +211,13 @@ void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
TRUE Error sending data to client
*/
-static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"};
-static int warning_level_length[]= { 4, 7, 5, 1 };
+LEX_STRING warning_level_names[]=
+{
+ {(char*) STRING_WITH_LEN("Note")},
+ {(char*) STRING_WITH_LEN("Warning")},
+ {(char*) STRING_WITH_LEN("Error")},
+ {(char*) STRING_WITH_LEN("?")}
+};
bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
{
@@ -246,8 +251,8 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
if (idx > unit->select_limit_cnt)
break;
protocol->prepare_for_resend();
- protocol->store(warning_level_names[err->level],
- warning_level_length[err->level], system_charset_info);
+ protocol->store(warning_level_names[err->level].str,
+ warning_level_names[err->level].length, system_charset_info);
protocol->store((uint32) err->code);
protocol->store(err->msg, strlen(err->msg), system_charset_info);
if (protocol->write())