From: Date: July 18 2008 2:08pm Subject: bzr commit into mysql-5.0 branch (holyfoot:2648) Bug#37428 List-Archive: http://lists.mysql.com/commits/50037 X-Bug: 37428 Message-Id: <20080718120837.B6C802C380A5@hfmain.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit #At file:///home/hf/work/mysql_common/37428/ 2648 Alexey Botchkov 2008-07-18 Bug#37428 Potential security issue with UDFs - linux shellcode execution. plugin_dir option backported from 5.1 modified: sql/mysql_priv.h sql/mysqld.cc sql/set_var.cc sql/sql_udf.cc sql/unireg.h per-file messages: sql/mysql_priv.h Bug#37428 Potential security issue with UDFs - linux shellcode execution. opt_plugin_dir and opt_plugin_dir_ptr declared. sql/mysqld.cc Bug#37428 Potential security issue with UDFs - linux shellcode execution. 'plugin_dir' option added sql/set_var.cc Bug#37428 Potential security issue with UDFs - linux shellcode execution. 'plugin_dir' option added. sql/sql_udf.cc Bug#37428 Potential security issue with UDFs - linux shellcode execution. opt_plugin_dir added to the udf->dl path. Warn if it's not specified. sql/unireg.h Bug#37428 Potential security issue with UDFs - linux shellcode execution. PLUGINDIR defined. === modified file 'sql/mysql_priv.h' --- a/sql/mysql_priv.h 2008-03-28 11:31:52 +0000 +++ b/sql/mysql_priv.h 2008-07-18 12:07:55 +0000 @@ -1342,6 +1342,9 @@ extern char *default_tz_name; extern my_bool opt_large_pages; extern uint opt_large_page_size; +extern char *opt_plugin_dir_ptr; +extern char opt_plugin_dir[FN_REFLEN]; + extern MYSQL_LOG mysql_log,mysql_slow_log,mysql_bin_log; extern FILE *bootstrap_file; extern int bootstrap_error; === modified file 'sql/mysqld.cc' --- a/sql/mysqld.cc 2008-06-03 10:12:37 +0000 +++ b/sql/mysqld.cc 2008-07-18 12:07:55 +0000 @@ -324,6 +324,9 @@ arg_cmp_func Arg_comparator::comparator_ /* static variables */ +char opt_plugin_dir[FN_REFLEN]; +char *opt_plugin_dir_ptr; + static bool lower_case_table_names_used= 0; static bool volatile select_thread_in_use, signal_thread_in_use; static bool volatile ready_to_exit; @@ -4984,6 +4987,7 @@ enum options_mysqld OPT_OLD_STYLE_USER_LIMITS, OPT_LOG_SLOW_ADMIN_STATEMENTS, OPT_TABLE_LOCK_WAIT_TIMEOUT, + OPT_PLUGIN_DIR, OPT_PORT_OPEN_TIMEOUT, OPT_MERGE, OPT_INNODB_ROLLBACK_ON_TIMEOUT, @@ -6216,6 +6220,10 @@ The minimum value for this variable is 4 (gptr*) &global_system_variables.optimizer_search_depth, (gptr*) &max_system_variables.optimizer_search_depth, 0, GET_ULONG, OPT_ARG, MAX_TABLES+1, 0, MAX_TABLES+2, 0, 1, 0}, + {"plugin_dir", OPT_PLUGIN_DIR, + "Directory for plugins.", + (gptr*) &opt_plugin_dir_ptr, (gptr*) &opt_plugin_dir_ptr, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE, "The size of the buffer that is allocated when preloading indexes", (gptr*) &global_system_variables.preload_buff_size, @@ -7753,6 +7761,9 @@ static void fix_paths(void) (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home); (void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home); + (void) my_load_path(opt_plugin_dir, opt_plugin_dir_ptr ? opt_plugin_dir_ptr : + "", ""); + opt_plugin_dir_ptr= opt_plugin_dir; char *sharedir=get_relative_path(SHAREDIR); if (test_if_hard_path(sharedir)) === modified file 'sql/set_var.cc' --- a/sql/set_var.cc 2008-03-28 18:02:27 +0000 +++ b/sql/set_var.cc 2008-07-18 12:07:55 +0000 @@ -1026,6 +1026,7 @@ struct show_var_st init_vars[]= { {sys_optimizer_search_depth.name,(char*) &sys_optimizer_search_depth, SHOW_SYS}, {"pid_file", (char*) pidfile_name, SHOW_CHAR}, + {"plugin_dir", (char*) opt_plugin_dir, SHOW_CHAR}, {"port", (char*) &mysqld_port, SHOW_INT}, {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, === modified file 'sql/sql_udf.cc' --- a/sql/sql_udf.cc 2007-11-09 10:41:50 +0000 +++ b/sql/sql_udf.cc 2008-07-18 12:07:55 +0000 @@ -214,7 +214,17 @@ void udf_init() void *dl = find_udf_dl(tmp->dl); if (dl == NULL) { - if (!(dl = dlopen(tmp->dl, RTLD_NOW))) + char dlpath[FN_REFLEN]; + if (*opt_plugin_dir) + strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", tmp->dl, + NullS); + else + { + strxnmov(dlpath, sizeof(dlpath)-1, tmp->dl, NullS); + push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, + "plugin_dir was not specified"); + } + if (!(dl = dlopen(dlpath, RTLD_NOW))) { /* Print warning to log */ sql_print_error(ER(ER_CANT_OPEN_LIBRARY), tmp->dl,errno,dlerror()); @@ -443,8 +453,18 @@ int mysql_create_function(THD *thd,udf_f } if (!(dl = find_udf_dl(udf->dl))) { - DBUG_PRINT("info", ("Calling dlopen, udf->dl: %s", udf->dl)); - if (!(dl = dlopen(udf->dl, RTLD_NOW))) + char dlpath[FN_REFLEN]; + if (*opt_plugin_dir) + strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", udf->dl, + NullS); + else + { + strxnmov(dlpath, sizeof(dlpath)-1, udf->dl, NullS); + push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, + "plugin_dir was not specified"); + } + DBUG_PRINT("info", ("Calling dlopen, udf->dl: %s", dlpath)); + if (!(dl = dlopen(dlpath, RTLD_NOW))) { DBUG_PRINT("error",("dlopen of %s failed, error: %d (%s)", udf->dl,errno,dlerror())); === modified file 'sql/unireg.h' --- a/sql/unireg.h 2008-04-10 00:34:38 +0000 +++ b/sql/unireg.h 2008-07-18 12:07:55 +0000 @@ -35,6 +35,9 @@ #ifndef SHAREDIR #define SHAREDIR "share/" #endif +#ifndef PLUGINDIR +#define PLUGINDIR "lib/plugin" +#endif #define ER(X) errmesg[(X) - ER_ERROR_FIRST] #define ER_SAFE(X) (((X) >= ER_ERROR_FIRST && (X) <= ER_ERROR_LAST) ? ER(X) : "Invalid error code")