diff --git a/mysql-test/suite/plugins/r/server_audit_bugs.result b/mysql-test/suite/plugins/r/server_audit_bugs.result new file mode 100644 index 00000000000..63e007f266b --- /dev/null +++ b/mysql-test/suite/plugins/r/server_audit_bugs.result @@ -0,0 +1,20 @@ +# +# MDEV-34074 server_audit crashes in get_loc_info() with NULL loc_info +# +INSTALL PLUGIN server_audit SONAME 'server_audit'; +UNINSTALL PLUGIN server_audit; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown +connect con1,localhost,root,,; +DO @@session.aria_repair_threads; +connection default; +INSTALL PLUGIN server_audit SONAME 'server_audit'; +connection con1; +SELECT 1; +1 +1 +connection default; +disconnect con1; +UNINSTALL PLUGIN server_audit; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown diff --git a/mysql-test/suite/plugins/t/server_audit_bugs.test b/mysql-test/suite/plugins/t/server_audit_bugs.test new file mode 100644 index 00000000000..1b37a7b74ac --- /dev/null +++ b/mysql-test/suite/plugins/t/server_audit_bugs.test @@ -0,0 +1,32 @@ +--source include/not_embedded.inc + +if (!$SERVER_AUDIT_SO) { + skip No SERVER_AUDIT plugin; +} + +--echo # +--echo # MDEV-34074 server_audit crashes in get_loc_info() with NULL loc_info +--echo # +# THDVAR() could return NULL if the plugin was previously uninstalled - +# uninstall wipes the session-variable placeholders and they are not +# reinitialized on re-install. Black magic to reproduce: install and +# uninstall server_audit, create a new session and touch any plugin session +# variable (aria_repair_threads), then install server_audit again. +# The "will be uninstalled on shutdown" warning below is misleading: the +# plugin is actually reaped as soon as its last reference drops (which is +# what wipes the placeholders), not on shutdown. +INSTALL PLUGIN server_audit SONAME 'server_audit'; +UNINSTALL PLUGIN server_audit; + +connect (con1,localhost,root,,); +DO @@session.aria_repair_threads; + +connection default; +INSTALL PLUGIN server_audit SONAME 'server_audit'; + +connection con1; +SELECT 1; + +connection default; +disconnect con1; +UNINSTALL PLUGIN server_audit; diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index 5d37186aeaa..1697441a34c 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -839,7 +839,8 @@ static struct connection_info *get_loc_info(MYSQL_THD thd) return (struct connection_info *) THDVAR(thd, loc_info); */ struct connection_info *ci= (struct connection_info *) THDVAR(thd, loc_info); - if ((size_t) ci->user_length > sizeof(ci->user)) + /* THDVAR can return NULL if the plugin was previously uninstalled (MDEV-34074). */ + if (ci && (size_t) ci->user_length > sizeof(ci->user)) { ci->user_length= 0; ci->host_length= 0; @@ -2073,7 +2074,9 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev) cn= get_loc_info(thd); } - update_connection_info(thd, cn, event_class, ev, &after_action); + /* Without loc_info (see get_loc_info) the session is not audited. */ + if (cn) + update_connection_info(thd, cn, event_class, ev, &after_action); if (!logging) { @@ -2631,7 +2634,7 @@ static void log_current_query(MYSQL_THD thd) if (!thd) return; cn= get_loc_info(thd); - if (!ci_needs_setup(cn) && cn->query_length) + if (cn && !ci_needs_setup(cn) && cn->query_length) { cn->log_always= 1; log_statement_ex(cn, cn->query_time, thd_get_thread_id(thd),