Commit 515de310 authored by Sergey Glukhov's avatar Sergey Glukhov
Browse files

Bug#37428 Potential security issue with UDFs - linux shellcode execution.

plugin_dir option backported from 5.1
parent 9bc9ddd5
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
drop table if exists t1;
CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
Warnings:
Warning	1105	plugin_dir was not specified
CREATE FUNCTION myfunc_double RETURNS REAL SONAME "UDF_EXAMPLE_LIB";
CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB";
ERROR HY000: Can't find function 'myfunc_nonexist' in library
@@ -197,6 +199,8 @@ DROP FUNCTION avgcost;
select * from mysql.func;
name	ret	dl	type
CREATE FUNCTION is_const RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
Warnings:
Warning	1105	plugin_dir was not specified
select IS_const(3);
IS_const(3)
const
@@ -206,6 +210,8 @@ name ret dl type
select is_const(3);
ERROR 42000: FUNCTION test.is_const does not exist
CREATE FUNCTION is_const RETURNS STRING SONAME "UDF_EXAMPLE_LIB";
Warnings:
Warning	1105	plugin_dir was not specified
select
is_const(3) as const,
is_const(3.14) as const,
+3 −0
Original line number Diff line number Diff line
@@ -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;
+11 −0
Original line number Diff line number Diff line
@@ -324,6 +324,9 @@ arg_cmp_func Arg_comparator::comparator_matrix[5][2] =

/* 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 4096.",
   (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))
+1 −0
Original line number Diff line number Diff line
@@ -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},
+23 −3
Original line number Diff line number Diff line
@@ -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_func *udf)
  }
  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()));
Loading