Commit adb35154 authored by Sergey Vojtovich's avatar Sergey Vojtovich

Backport from 6.0-codebase.

Bug #36098 Audit plugin (wl 3771) feature disabled in 6.0
avoid recusrive locking of LOCK_plugin

include/mysql/plugin_audit.h:
  fix incorrect version
sql/log.cc:
  move the common code to a shared header
sql/mysqld.cc:
  restore the deleted functionality
sql/set_var.cc:
  remove unused parameter
sql/sql_audit.h:
  two inline convenience functions
sql/sql_parse.cc:
  use a simplified convenience call
sql/sql_plugin.cc:
  unlock LOCK_plugin for plugin->init() call, add missing OOM check,
  issue "unknown variable" error in find_sys_var, not down the stack
parent 540f8521
...@@ -24,8 +24,7 @@ ...@@ -24,8 +24,7 @@
#define MYSQL_AUDIT_CLASS_MASK_SIZE 1 #define MYSQL_AUDIT_CLASS_MASK_SIZE 1
#define MYSQL_AUDIT_INTERFACE_VERSION ( 0x010000 | MYSQL_AUDIT_CLASS_MASK_SIZE ) #define MYSQL_AUDIT_INTERFACE_VERSION 0x0100
/* /*
The first word in every event class struct indicates the specific The first word in every event class struct indicates the specific
......
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
/* max size of the log message */ /* max size of the log message */
#define MAX_LOG_BUFFER_SIZE 1024 #define MAX_LOG_BUFFER_SIZE 1024
#define MAX_USER_HOST_SIZE 512
#define MAX_TIME_SIZE 32 #define MAX_TIME_SIZE 32
#define MY_OFF_T_UNDEF (~(my_off_t)0UL) #define MY_OFF_T_UNDEF (~(my_off_t)0UL)
...@@ -1069,7 +1068,6 @@ bool LOGGER::general_log_write(THD *thd, enum enum_server_command command, ...@@ -1069,7 +1068,6 @@ bool LOGGER::general_log_write(THD *thd, enum enum_server_command command,
bool error= FALSE; bool error= FALSE;
Log_event_handler **current_handler= general_log_handler_list; Log_event_handler **current_handler= general_log_handler_list;
char user_host_buff[MAX_USER_HOST_SIZE + 1]; char user_host_buff[MAX_USER_HOST_SIZE + 1];
Security_context *sctx= thd->security_ctx;
uint user_host_len= 0; uint user_host_len= 0;
time_t current_time; time_t current_time;
...@@ -1081,21 +1079,15 @@ bool LOGGER::general_log_write(THD *thd, enum enum_server_command command, ...@@ -1081,21 +1079,15 @@ bool LOGGER::general_log_write(THD *thd, enum enum_server_command command,
unlock(); unlock();
return 0; return 0;
} }
user_host_len= strxnmov(user_host_buff, MAX_USER_HOST_SIZE, user_host_len= make_user_name(thd, user_host_buff);
sctx->priv_user ? sctx->priv_user : "", "[",
sctx->user ? sctx->user : "", "] @ ",
sctx->host ? sctx->host : "", " [",
sctx->ip ? sctx->ip : "", "]", NullS) -
user_host_buff;
current_time= my_time(0); current_time= my_time(0);
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_LOG, 0, current_time, mysql_audit_general_log(thd, current_time,
user_host_buff, user_host_len, user_host_buff, user_host_len,
command_name[(uint) command].str, command_name[(uint) command].str,
command_name[(uint) command].length, command_name[(uint) command].length,
query, query_length, query, query_length);
thd->variables.character_set_client,0);
while (*current_handler) while (*current_handler)
error|= (*current_handler++)-> error|= (*current_handler++)->
......
...@@ -2923,15 +2923,10 @@ void my_message_sql(uint error, const char *str, myf MyFlags) ...@@ -2923,15 +2923,10 @@ void my_message_sql(uint error, const char *str, myf MyFlags)
error= ER_UNKNOWN_ERROR; error= ER_UNKNOWN_ERROR;
} }
mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_ERROR, error, str);
if (thd) if (thd)
{ {
mysql_audit_general(thd,MYSQL_AUDIT_GENERAL_ERROR,error,my_time(0),
0,0,str,str ? strlen(str) : 0,
thd->query(), thd->query_length(),
thd->variables.character_set_client,
thd->warning_info->current_row_for_warning());
if (MyFlags & ME_FATALERROR) if (MyFlags & ME_FATALERROR)
thd->is_fatal_error= 1; thd->is_fatal_error= 1;
(void) thd->raise_condition(error, (void) thd->raise_condition(error,
......
...@@ -3519,7 +3519,6 @@ void set_var_free() ...@@ -3519,7 +3519,6 @@ void set_var_free()
@param str Name of system variable to find @param str Name of system variable to find
@param length Length of variable. zero means that we should use strlen() @param length Length of variable. zero means that we should use strlen()
on the variable on the variable
@param no_error Refuse to emit an error, even if one occurred.
@retval @retval
pointer pointer to variable definitions pointer pointer to variable definitions
...@@ -3527,7 +3526,7 @@ void set_var_free() ...@@ -3527,7 +3526,7 @@ void set_var_free()
0 Unknown variable (error message is given) 0 Unknown variable (error message is given)
*/ */
sys_var *intern_find_sys_var(const char *str, uint length, bool no_error) sys_var *intern_find_sys_var(const char *str, uint length)
{ {
sys_var *var; sys_var *var;
...@@ -3537,9 +3536,6 @@ sys_var *intern_find_sys_var(const char *str, uint length, bool no_error) ...@@ -3537,9 +3536,6 @@ sys_var *intern_find_sys_var(const char *str, uint length, bool no_error)
*/ */
var= (sys_var*) my_hash_search(&system_variable_hash, var= (sys_var*) my_hash_search(&system_variable_hash,
(uchar*) str, length ? length : strlen(str)); (uchar*) str, length ? length : strlen(str));
if (!(var || no_error))
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
return var; return var;
} }
......
...@@ -34,18 +34,21 @@ extern void mysql_audit_notify(THD *thd, uint event_class, ...@@ -34,18 +34,21 @@ extern void mysql_audit_notify(THD *thd, uint event_class,
uint event_subtype, ...); uint event_subtype, ...);
extern void mysql_audit_release(THD *thd); extern void mysql_audit_release(THD *thd);
#define MAX_USER_HOST_SIZE 512
static inline uint make_user_name(THD *thd, char *buf)
{
Security_context *sctx= thd->security_ctx;
return strxnmov(buf, MAX_USER_HOST_SIZE,
sctx->priv_user ? sctx->priv_user : "", "[",
sctx->user ? sctx->user : "", "] @ ",
sctx->host ? sctx->host : "", " [",
sctx->ip ? sctx->ip : "", "]", NullS) - buf;
}
/** /**
Call audit plugins of GENERAL audit class. Call audit plugins of GENERAL audit class, MYSQL_AUDIT_GENERAL_LOG subtype.
event_subtype should be set to one of:
MYSQL_AUDIT_GENERAL_LOG
MYSQL_AUDIT_GENERAL_ERROR
MYSQL_AUDIT_GENERAL_RESULT
@param[in] thd @param[in] thd
@param[in] event_subtype Type of general audit event.
@param[in] error_code Error code
@param[in] time time that event occurred @param[in] time time that event occurred
@param[in] user User name @param[in] user User name
@param[in] userlen User name length @param[in] userlen User name length
...@@ -53,24 +56,74 @@ extern void mysql_audit_release(THD *thd); ...@@ -53,24 +56,74 @@ extern void mysql_audit_release(THD *thd);
@param[in] cmdlen Command name length @param[in] cmdlen Command name length
@param[in] query Query string @param[in] query Query string
@param[in] querylen Query string length @param[in] querylen Query string length
@param[in] clientcs Charset of query string
@param[in] rows Number of affected rows
*/ */
static inline static inline
void mysql_audit_general(THD *thd, uint event_subtype, void mysql_audit_general_log(THD *thd, time_t time,
int error_code, time_t time,
const char *user, uint userlen, const char *user, uint userlen,
const char *cmd, uint cmdlen, const char *cmd, uint cmdlen,
const char *query, uint querylen, const char *query, uint querylen)
CHARSET_INFO *clientcs,
ha_rows rows)
{ {
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
if (mysql_global_audit_mask[0] & MYSQL_AUDIT_GENERAL_CLASSMASK) if (mysql_global_audit_mask[0] & MYSQL_AUDIT_GENERAL_CLASSMASK)
{
CHARSET_INFO *clientcs= thd ? thd->variables.character_set_client
: global_system_variables.character_set_client;
mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, MYSQL_AUDIT_GENERAL_LOG,
0, time, user, userlen, cmd, cmdlen,
query, querylen, clientcs, 0);
}
#endif
}
/**
Call audit plugins of GENERAL audit class.
event_subtype should be set to one of:
MYSQL_AUDIT_GENERAL_ERROR
MYSQL_AUDIT_GENERAL_RESULT
@param[in] thd
@param[in] event_subtype Type of general audit event.
@param[in] error_code Error code
@param[in] msg Message
*/
static inline
void mysql_audit_general(THD *thd, uint event_subtype,
int error_code, const char *msg)
{
#ifndef EMBEDDED_LIBRARY
if (mysql_global_audit_mask[0] & MYSQL_AUDIT_GENERAL_CLASSMASK)
{
time_t time= my_time(0);
uint msglen= msg ? strlen(msg) : 0;
const char *query, *user;
uint querylen, userlen;
char user_buff[MAX_USER_HOST_SIZE];
CHARSET_INFO *clientcs;
ha_rows rows;
if (thd)
{
query= thd->query();
querylen= thd->query_length();
user= user_buff;
userlen= make_user_name(thd, user_buff);
clientcs= thd->variables.character_set_client;
rows= thd->warning_info->current_row_for_warning();
}
else
{
query= user= 0;
querylen= userlen= 0;
clientcs= global_system_variables.character_set_client;
rows= 0;
}
mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, event_subtype, mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, event_subtype,
error_code, time, user, userlen, cmd, cmdlen, error_code, time, user, userlen, msg, msglen,
query, querylen, clientcs, rows); query, querylen, clientcs, rows);
}
#endif #endif
} }
......
...@@ -1485,13 +1485,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ...@@ -1485,13 +1485,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
close_thread_tables(thd); close_thread_tables(thd);
if (!thd->is_error() && !thd->killed_errno()) if (!thd->is_error() && !thd->killed_errno())
{ mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0);
mysql_audit_general(thd,MYSQL_AUDIT_GENERAL_RESULT,0,my_time(0),
0,0,0,0,
thd->query(), thd->query_length(),
thd->variables.character_set_client,
thd->warning_info->current_row_for_warning());
}
log_slow_statement(thd); log_slow_statement(thd);
......
...@@ -229,7 +229,7 @@ static void reap_plugins(void); ...@@ -229,7 +229,7 @@ static void reap_plugins(void);
/* declared in set_var.cc */ /* declared in set_var.cc */
extern sys_var *intern_find_sys_var(const char *str, uint length, bool no_error); extern sys_var *intern_find_sys_var(const char *str, uint length);
extern bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd, extern bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
const char *name, longlong val); const char *name, longlong val);
...@@ -1014,6 +1014,9 @@ static int plugin_initialize(struct st_plugin_int *plugin) ...@@ -1014,6 +1014,9 @@ static int plugin_initialize(struct st_plugin_int *plugin)
DBUG_ENTER("plugin_initialize"); DBUG_ENTER("plugin_initialize");
safe_mutex_assert_owner(&LOCK_plugin); safe_mutex_assert_owner(&LOCK_plugin);
DBUG_ASSERT(plugin->state == PLUGIN_IS_UNINITIALIZED);
pthread_mutex_unlock(&LOCK_plugin);
if (plugin_type_initialize[plugin->plugin->type]) if (plugin_type_initialize[plugin->plugin->type])
{ {
if ((*plugin_type_initialize[plugin->plugin->type])(plugin)) if ((*plugin_type_initialize[plugin->plugin->type])(plugin))
...@@ -1033,6 +1036,8 @@ static int plugin_initialize(struct st_plugin_int *plugin) ...@@ -1033,6 +1036,8 @@ static int plugin_initialize(struct st_plugin_int *plugin)
} }
} }
pthread_mutex_lock(&LOCK_plugin);
plugin->state= PLUGIN_IS_READY; plugin->state= PLUGIN_IS_READY;
if (plugin->plugin->status_vars) if (plugin->plugin->status_vars)
...@@ -1050,9 +1055,10 @@ static int plugin_initialize(struct st_plugin_int *plugin) ...@@ -1050,9 +1055,10 @@ static int plugin_initialize(struct st_plugin_int *plugin)
{0, 0, SHOW_UNDEF} {0, 0, SHOW_UNDEF}
}; };
if (add_status_vars(array)) // add_status_vars makes a copy if (add_status_vars(array)) // add_status_vars makes a copy
goto err; goto err1;
#else #else
add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy if (add_status_vars(plugin->plugin->status_vars))
goto err1;
#endif /* FIX_LATER */ #endif /* FIX_LATER */
} }
...@@ -1074,6 +1080,8 @@ static int plugin_initialize(struct st_plugin_int *plugin) ...@@ -1074,6 +1080,8 @@ static int plugin_initialize(struct st_plugin_int *plugin)
DBUG_RETURN(0); DBUG_RETURN(0);
err: err:
pthread_mutex_lock(&LOCK_plugin);
err1:
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -1686,7 +1694,6 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl ...@@ -1686,7 +1694,6 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl
} }
else else
{ {
DBUG_ASSERT(tmp->state == PLUGIN_IS_UNINITIALIZED);
if (plugin_initialize(tmp)) if (plugin_initialize(tmp))
{ {
my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str, my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str,
...@@ -2164,7 +2171,7 @@ sys_var *find_sys_var(THD *thd, const char *str, uint length) ...@@ -2164,7 +2171,7 @@ sys_var *find_sys_var(THD *thd, const char *str, uint length)
pthread_mutex_lock(&LOCK_plugin); pthread_mutex_lock(&LOCK_plugin);
rw_rdlock(&LOCK_system_variables_hash); rw_rdlock(&LOCK_system_variables_hash);
if ((var= intern_find_sys_var(str, length, false)) && if ((var= intern_find_sys_var(str, length)) &&
(pi= var->cast_pluginvar())) (pi= var->cast_pluginvar()))
{ {
rw_unlock(&LOCK_system_variables_hash); rw_unlock(&LOCK_system_variables_hash);
...@@ -2183,11 +2190,7 @@ sys_var *find_sys_var(THD *thd, const char *str, uint length) ...@@ -2183,11 +2190,7 @@ sys_var *find_sys_var(THD *thd, const char *str, uint length)
rw_unlock(&LOCK_system_variables_hash); rw_unlock(&LOCK_system_variables_hash);
pthread_mutex_unlock(&LOCK_plugin); pthread_mutex_unlock(&LOCK_plugin);
/* if (!var)
If the variable exists but the plugin it is associated with is not ready
then the intern_plugin_lock did not raise an error, so we do it here.
*/
if (pi && !var)
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str); my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
DBUG_RETURN(var); DBUG_RETURN(var);
} }
...@@ -2390,7 +2393,7 @@ static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) ...@@ -2390,7 +2393,7 @@ static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock)
st_bookmark *v= (st_bookmark*) my_hash_element(&bookmark_hash,idx); st_bookmark *v= (st_bookmark*) my_hash_element(&bookmark_hash,idx);
if (v->version <= thd->variables.dynamic_variables_version || if (v->version <= thd->variables.dynamic_variables_version ||
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) || !(var= intern_find_sys_var(v->key + 1, v->name_len)) ||
!(pi= var->cast_pluginvar()) || !(pi= var->cast_pluginvar()) ||
v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK)) v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
continue; continue;
...@@ -2483,7 +2486,7 @@ static void cleanup_variables(THD *thd, struct system_variables *vars) ...@@ -2483,7 +2486,7 @@ static void cleanup_variables(THD *thd, struct system_variables *vars)
{ {
v= (st_bookmark*) my_hash_element(&bookmark_hash, idx); v= (st_bookmark*) my_hash_element(&bookmark_hash, idx);
if (v->version > vars->dynamic_variables_version || if (v->version > vars->dynamic_variables_version ||
!(var= intern_find_sys_var(v->key + 1, v->name_len, true)) || !(var= intern_find_sys_var(v->key + 1, v->name_len)) ||
!(pivar= var->cast_pluginvar()) || !(pivar= var->cast_pluginvar()) ||
v->key[0] != (pivar->plugin_var->flags & PLUGIN_VAR_TYPEMASK)) v->key[0] != (pivar->plugin_var->flags & PLUGIN_VAR_TYPEMASK))
continue; continue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment