BUG#57108: mysqld crashes when I attempt to install plugin
If a relative path is supplied to option --defaults-file or --defaults-extra-file, the server will crash when executing an INSTALL PLUGIN command. The reason is that the defaults file is initially read relative the current working directory when the server is started, but when INSTALL PLUGIN is executed, the server has changed working directory to the data directory. Since there is no check that the call to my_load_defaults() inside mysql_install_plugin(), the subsequence call to free_defaults() will crash the server. This patch fixes the problem by: - Prepending the current working directory to the file name when a relative path is given to the --defaults-file or --defaults- extra-file option the first time my_load_defaults() is called, which is just after the server has started in main(). - Adding a check of the return value of my_load_defaults() inside mysql_install_plugin() and aborting command (with an error) if an error is returned. - It also adds a check of the return value for load_defaults in lib_sql.cc for the embedded server since that was missing. To test that the relative files for the options --defaults-file and --defaults-extra-file is handled properly, mysql-test-run.pl is also changed to not add a --defaults-file option if one is provided in the tests *.opt file.
This commit is contained in:
parent
69aea87d5f
commit
d817b7cb8a
@ -256,7 +256,7 @@ extern my_bool my_disable_locking, my_disable_async_io,
|
||||
extern char wild_many,wild_one,wild_prefix;
|
||||
extern const char *charsets_dir;
|
||||
/* from default.c */
|
||||
extern char *my_defaults_extra_file;
|
||||
extern const char *my_defaults_extra_file;
|
||||
extern const char *my_defaults_group_suffix;
|
||||
extern const char *my_defaults_file;
|
||||
|
||||
|
@ -506,7 +506,8 @@ int init_embedded_server(int argc, char **argv, char **groups)
|
||||
|
||||
orig_argc= *argcp;
|
||||
orig_argv= *argvp;
|
||||
load_defaults("my", (const char **)groups, argcp, argvp);
|
||||
if (load_defaults("my", (const char **)groups, argcp, argvp))
|
||||
return 1;
|
||||
defaults_argc= *argcp;
|
||||
defaults_argv= *argvp;
|
||||
remaining_argc= argc;
|
||||
|
@ -4406,7 +4406,13 @@ sub mysqld_arguments ($$$) {
|
||||
my $mysqld= shift;
|
||||
my $extra_opts= shift;
|
||||
|
||||
my @defaults = grep(/^--defaults-file=/, @$extra_opts);
|
||||
if (@defaults > 0) {
|
||||
mtr_add_arg($args, pop(@defaults))
|
||||
}
|
||||
else {
|
||||
mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
|
||||
}
|
||||
|
||||
# When mysqld is run by a root user(euid is 0), it will fail
|
||||
# to start unless we specify what user to run as, see BUG#30630
|
||||
@ -4442,6 +4448,9 @@ sub mysqld_arguments ($$$) {
|
||||
my $found_skip_core= 0;
|
||||
foreach my $arg ( @$extra_opts )
|
||||
{
|
||||
# Skip --defaults-file option since it's handled above.
|
||||
next if $arg =~ /^--defaults-file/;
|
||||
|
||||
# Allow --skip-core-file to be set in <testname>-[master|slave].opt file
|
||||
if ($arg eq "--skip-core-file")
|
||||
{
|
||||
|
95
mysql-test/std_data/bug57108.cnf
Normal file
95
mysql-test/std_data/bug57108.cnf
Normal file
@ -0,0 +1,95 @@
|
||||
[mysqld]
|
||||
open-files-limit=1024
|
||||
character-set-server=latin1
|
||||
connect-timeout=4711
|
||||
log-bin-trust-function-creators=1
|
||||
key_buffer_size=1M
|
||||
sort_buffer=256K
|
||||
max_heap_table_size=1M
|
||||
loose-innodb_data_file_path=ibdata1:10M:autoextend
|
||||
loose-innodb_buffer_pool_size=8M
|
||||
loose-innodb_write_io_threads=2
|
||||
loose-innodb_read_io_threads=2
|
||||
loose-innodb_log_buffer_size=1M
|
||||
loose-innodb_log_file_size=5M
|
||||
loose-innodb_additional_mem_pool_size=1M
|
||||
loose-innodb_log_files_in_group=2
|
||||
slave-net-timeout=120
|
||||
log-bin=mysqld-bin
|
||||
loose-enable-performance-schema
|
||||
loose-performance-schema-max-mutex-instances=10000
|
||||
loose-performance-schema-max-rwlock-instances=10000
|
||||
loose-performance-schema-max-table-instances=500
|
||||
loose-performance-schema-max-table-handles=1000
|
||||
binlog-direct-non-transactional-updates
|
||||
|
||||
[mysql]
|
||||
default-character-set=latin1
|
||||
|
||||
[mysqlshow]
|
||||
default-character-set=latin1
|
||||
|
||||
[mysqlimport]
|
||||
default-character-set=latin1
|
||||
|
||||
[mysqlcheck]
|
||||
default-character-set=latin1
|
||||
|
||||
[mysql_upgrade]
|
||||
default-character-set=latin1
|
||||
tmpdir=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/tmp
|
||||
|
||||
[mysqld.1]
|
||||
#!run-master-sh
|
||||
log-bin=master-bin
|
||||
loose-enable-performance-schema
|
||||
basedir=/home/bzr/bugs/b57108-5.5-bugteam
|
||||
tmpdir=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/tmp/mysqld.1
|
||||
character-sets-dir=/home/bzr/bugs/b57108-5.5-bugteam/sql/share/charsets
|
||||
lc-messages-dir=/home/bzr/bugs/b57108-5.5-bugteam/sql/share/
|
||||
datadir=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/mysqld.1/data
|
||||
pid-file=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/run/mysqld.1.pid
|
||||
#host=localhost
|
||||
port=13000
|
||||
socket=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/tmp/mysqld.1.sock
|
||||
#log-error=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/log/mysqld.1.err
|
||||
general_log=1
|
||||
general_log_file=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/mysqld.1/mysqld.log
|
||||
slow_query_log=1
|
||||
slow_query_log_file=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/mysqld.1/mysqld-slow.log
|
||||
#user=root
|
||||
#password=
|
||||
server-id=1
|
||||
secure-file-priv=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var
|
||||
ssl-ca=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/std_data/cacert.pem
|
||||
ssl-cert=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/std_data/server-cert.pem
|
||||
ssl-key=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/std_data/server-key.pem
|
||||
|
||||
[mysqlbinlog]
|
||||
disable-force-if-open
|
||||
character-sets-dir=/home/bzr/bugs/b57108-5.5-bugteam/sql/share/charsets
|
||||
|
||||
[ENV]
|
||||
MASTER_MYPORT=13000
|
||||
MASTER_MYSOCK=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/tmp/mysqld.1.sock
|
||||
|
||||
[client]
|
||||
password=
|
||||
user=root
|
||||
port=13000
|
||||
host=localhost
|
||||
socket=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/tmp/mysqld.1.sock
|
||||
|
||||
[mysqltest]
|
||||
ssl-ca=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/std_data/cacert.pem
|
||||
ssl-cert=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/std_data/client-cert.pem
|
||||
ssl-key=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/std_data/client-key.pem
|
||||
skip-ssl=1
|
||||
|
||||
[client.1]
|
||||
password=
|
||||
user=root
|
||||
port=13000
|
||||
host=localhost
|
||||
socket=/home/bzr/bugs/b57108-5.5-bugteam/mysql-test/var/tmp/mysqld.1.sock
|
||||
|
5
mysql-test/suite/bugs/r/bug57108.result
Normal file
5
mysql-test/suite/bugs/r/bug57108.result
Normal file
@ -0,0 +1,5 @@
|
||||
INSTALL PLUGIN example SONAME 'ha_example.so';
|
||||
SELECT @@global.connect_timeout AS connect_timeout, @@global.local_infile AS local_infile;
|
||||
connect_timeout 4711
|
||||
local_infile 1
|
||||
UNINSTALL PLUGIN example;
|
2
mysql-test/suite/bugs/t/bug57108-master.opt
Normal file
2
mysql-test/suite/bugs/t/bug57108-master.opt
Normal file
@ -0,0 +1,2 @@
|
||||
--defaults-file=std_data/bug57108.cnf
|
||||
$EXAMPLE_PLUGIN_OPT
|
12
mysql-test/suite/bugs/t/bug57108.test
Normal file
12
mysql-test/suite/bugs/t/bug57108.test
Normal file
@ -0,0 +1,12 @@
|
||||
--source include/not_windows_embedded.inc
|
||||
--source include/have_example_plugin.inc
|
||||
|
||||
# Test that we can install a plugin despite the fact that we have
|
||||
# switched directory after starting the server and am using a relative
|
||||
# --defaults-file.
|
||||
--replace_regex /\.dll/.so/
|
||||
eval INSTALL PLUGIN example SONAME $HA_EXAMPLE_SO;
|
||||
|
||||
--query_vertical SELECT @@global.connect_timeout AS connect_timeout, @@global.local_infile AS local_infile
|
||||
|
||||
UNINSTALL PLUGIN example;
|
@ -66,7 +66,9 @@
|
||||
const char *args_separator= "----args-separator----";
|
||||
const char *my_defaults_file=0;
|
||||
const char *my_defaults_group_suffix=0;
|
||||
char *my_defaults_extra_file=0;
|
||||
const char *my_defaults_extra_file=0;
|
||||
|
||||
static my_bool defaults_already_read= FALSE;
|
||||
|
||||
/* Which directories are searched for options (and in which order) */
|
||||
|
||||
@ -139,6 +141,36 @@ static const char **init_default_directories(MEM_ROOT *alloc);
|
||||
static char *remove_end_comment(char *ptr);
|
||||
|
||||
|
||||
/*
|
||||
Expand a file name so that the current working directory is added if
|
||||
the name is relative.
|
||||
|
||||
RETURNS
|
||||
0 All OK
|
||||
2 Out of memory or path to long
|
||||
3 Not able to get working directory
|
||||
*/
|
||||
|
||||
static int
|
||||
fn_expand(const char *filename, const char **filename_var)
|
||||
{
|
||||
char dir[FN_REFLEN], buf[FN_REFLEN];
|
||||
const int flags= MY_UNPACK_FILENAME | MY_SAFE_PATH | MY_RELATIVE_PATH;
|
||||
const char *result_path= NULL;
|
||||
DBUG_ENTER("fn_expand");
|
||||
DBUG_PRINT("enter", ("filename: %s, buf: 0x%lx", filename, (unsigned long) buf));
|
||||
if (my_getwd(dir, sizeof(dir), MYF(0)))
|
||||
DBUG_RETURN(3);
|
||||
DBUG_PRINT("debug", ("dir: %s", dir));
|
||||
if (fn_format(buf, filename, dir, NULL, flags) == NULL ||
|
||||
(result_path= my_strdup(buf, MYF(0))) == NULL)
|
||||
DBUG_RETURN(2);
|
||||
DBUG_PRINT("return", ("result: %s", result_path));
|
||||
DBUG_ASSERT(result_path != NULL);
|
||||
*filename_var= result_path;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/*
|
||||
Process config files in default directories.
|
||||
|
||||
@ -167,6 +199,7 @@ static char *remove_end_comment(char *ptr);
|
||||
0 ok
|
||||
1 given cinf_file doesn't exist
|
||||
2 out of memory
|
||||
3 Can't get current working directory
|
||||
|
||||
The global variable 'my_defaults_group_suffix' is updated with value for
|
||||
--defaults_group_suffix
|
||||
@ -189,11 +222,21 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv,
|
||||
if (! my_defaults_group_suffix)
|
||||
my_defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV));
|
||||
|
||||
if (forced_extra_defaults)
|
||||
my_defaults_extra_file= (char *) forced_extra_defaults;
|
||||
if (forced_extra_defaults && !defaults_already_read)
|
||||
{
|
||||
int error= fn_expand(forced_extra_defaults, &my_defaults_extra_file);
|
||||
if (error)
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
if (forced_default_file)
|
||||
my_defaults_file= forced_default_file;
|
||||
if (forced_default_file && !defaults_already_read)
|
||||
{
|
||||
int error= fn_expand(forced_default_file, &my_defaults_file);
|
||||
if (error)
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
defaults_already_read= TRUE;
|
||||
|
||||
/*
|
||||
We can only handle 'defaults-group-suffix' if we are called from
|
||||
@ -236,15 +279,15 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv,
|
||||
group->type_names[group->count]= 0;
|
||||
}
|
||||
|
||||
if (forced_default_file)
|
||||
if (my_defaults_file)
|
||||
{
|
||||
if ((error= search_default_file_with_ext(func, func_ctx, "", "",
|
||||
forced_default_file, 0)) < 0)
|
||||
my_defaults_file, 0)) < 0)
|
||||
goto err;
|
||||
if (error > 0)
|
||||
{
|
||||
fprintf(stderr, "Could not open required defaults file: %s\n",
|
||||
forced_default_file);
|
||||
my_defaults_file);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
@ -1738,7 +1738,11 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl
|
||||
mysql_mutex_lock(&LOCK_plugin);
|
||||
mysql_rwlock_wrlock(&LOCK_system_variables_hash);
|
||||
|
||||
my_load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv, NULL);
|
||||
if (my_load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv, NULL))
|
||||
{
|
||||
report_error(REPORT_TO_USER, ER_PLUGIN_IS_NOT_LOADED, name->str);
|
||||
goto err;
|
||||
}
|
||||
error= plugin_add(thd->mem_root, name, dl, &argc, argv, REPORT_TO_USER);
|
||||
if (argv)
|
||||
free_defaults(argv);
|
||||
|
Loading…
x
Reference in New Issue
Block a user