Commit 7839da60 authored by unknown's avatar unknown

BUG#28341 - Security issue still in library loading

UDF can be created from any library in any part of the server
LD_LIBRARY_PATH.

Allow to load udfs only from plugin_dir.
On windows, refuse to open udf in case it's path contains a slash.

No good test case for this bug because of imperfect error message
that includes error code and error string when it fails to dlopen a
library.


mysql-test/mysql-test-run.pl:
  Since plugins are allowed to be open only from plugin_dir:
  - there is no sence to update LD_LIBRARY_PATH
  - there is no sence to add plugin_dir arg by default
  - set UDF_EXAMPLE_LIB_OPT and EXAMPLE_PLUGIN_OPT to be used by
    udf and plugin tests accordingly.
mysql-test/r/plugin.result:
  Updated test result (we report addition warning).
sql/sql_udf.cc:
  Allow to load udfs only from plugin_dir.
  On windows, refuse to open udf in case it's path contains a slash.
mysql-test/t/plugin-master.opt:
  New BitKeeper file ``mysql-test/t/plugin-master.opt''
mysql-test/t/udf-master.opt:
  New BitKeeper file ``mysql-test/t/udf-master.opt''
parent 0ea67375
...@@ -1766,22 +1766,6 @@ sub environment_setup () { ...@@ -1766,22 +1766,6 @@ sub environment_setup () {
push(@ld_library_paths, "$glob_basedir/storage/ndb/src/.libs"); push(@ld_library_paths, "$glob_basedir/storage/ndb/src/.libs");
} }
# --------------------------------------------------------------------------
# Add the path where mysqld will find udf_example.so
# --------------------------------------------------------------------------
if ( $lib_udf_example )
{
push(@ld_library_paths, dirname($lib_udf_example));
}
# --------------------------------------------------------------------------
# Add the path where mysqld will find ha_example.so
# --------------------------------------------------------------------------
if ( $lib_example_plugin )
{
push(@ld_library_paths, dirname($lib_example_plugin));
}
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Valgrind need to be run with debug libraries otherwise it's almost # Valgrind need to be run with debug libraries otherwise it's almost
# impossible to add correct supressions, that means if "/usr/lib/debug" # impossible to add correct supressions, that means if "/usr/lib/debug"
...@@ -2060,12 +2044,16 @@ sub environment_setup () { ...@@ -2060,12 +2044,16 @@ sub environment_setup () {
# ---------------------------------------------------- # ----------------------------------------------------
$ENV{'UDF_EXAMPLE_LIB'}= $ENV{'UDF_EXAMPLE_LIB'}=
($lib_udf_example ? basename($lib_udf_example) : ""); ($lib_udf_example ? basename($lib_udf_example) : "");
$ENV{'UDF_EXAMPLE_LIB_OPT'}=
($lib_udf_example ? "--plugin_dir=" . dirname($lib_udf_example) : "");
# ---------------------------------------------------- # ----------------------------------------------------
# Add the path where mysqld will find ha_example.so # Add the path where mysqld will find ha_example.so
# ---------------------------------------------------- # ----------------------------------------------------
$ENV{'EXAMPLE_PLUGIN'}= $ENV{'EXAMPLE_PLUGIN'}=
($lib_example_plugin ? basename($lib_example_plugin) : ""); ($lib_example_plugin ? basename($lib_example_plugin) : "");
$ENV{'EXAMPLE_PLUGIN_OPT'}=
($lib_example_plugin ? "--plugin_dir=" . dirname($lib_example_plugin) : "");
# ---------------------------------------------------- # ----------------------------------------------------
# We are nice and report a bit about our settings # We are nice and report a bit about our settings
...@@ -3821,9 +3809,6 @@ sub mysqld_arguments ($$$$) { ...@@ -3821,9 +3809,6 @@ sub mysqld_arguments ($$$$) {
mtr_add_arg($args, "%s--ndb-extra-logging", $prefix); mtr_add_arg($args, "%s--ndb-extra-logging", $prefix);
} }
} }
mtr_add_arg($args, "%s--plugin_dir=%s", $prefix,
dirname($lib_example_plugin));
} }
else else
{ {
......
CREATE TABLE t1(a int) ENGINE=EXAMPLE; CREATE TABLE t1(a int) ENGINE=EXAMPLE;
Warnings: Warnings:
Error 1286 Unknown table engine 'EXAMPLE' Warning 1286 Unknown table engine 'EXAMPLE'
Warning 1266 Using storage engine MyISAM for table 't1'
DROP TABLE t1; DROP TABLE t1;
INSTALL PLUGIN example SONAME 'ha_example.so'; INSTALL PLUGIN example SONAME 'ha_example.so';
INSTALL PLUGIN EXAMPLE SONAME 'ha_example.so'; INSTALL PLUGIN EXAMPLE SONAME 'ha_example.so';
......
$UDF_EXAMPLE_LIB_OPT
...@@ -169,11 +169,15 @@ void udf_init() ...@@ -169,11 +169,15 @@ void udf_init()
Ensure that the .dll doesn't have a path Ensure that the .dll doesn't have a path
This is done to ensure that only approved dll from the system This is done to ensure that only approved dll from the system
directories are used (to make this even remotely secure). directories are used (to make this even remotely secure).
On windows we must check both FN_LIBCHAR and '/'.
*/ */
if (my_strchr(files_charset_info, dl_name, if (my_strchr(files_charset_info, dl_name,
dl_name + strlen(dl_name), FN_LIBCHAR) || dl_name + strlen(dl_name), FN_LIBCHAR) ||
check_string_char_length(&name, "", NAME_CHAR_LEN, IF_WIN(my_strchr(files_charset_info, dl_name,
system_charset_info, 1)) dl_name + strlen(dl_name), '/'), 0) ||
check_string_char_length(&name, "", NAME_CHAR_LEN,
system_charset_info, 1))
{ {
sql_print_error("Invalid row in mysql.func table for function '%.64s'", sql_print_error("Invalid row in mysql.func table for function '%.64s'",
name.str); name.str);
...@@ -190,10 +194,13 @@ void udf_init() ...@@ -190,10 +194,13 @@ void udf_init()
void *dl = find_udf_dl(tmp->dl); void *dl = find_udf_dl(tmp->dl);
if (dl == NULL) if (dl == NULL)
{ {
if (!(dl= dlopen(tmp->dl, RTLD_NOW))) char dlpath[FN_REFLEN];
strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", tmp->dl,
NullS);
if (!(dl= dlopen(dlpath, RTLD_NOW)))
{ {
/* Print warning to log */ /* Print warning to log */
sql_print_error(ER(ER_CANT_OPEN_LIBRARY), tmp->dl, errno, dlerror()); sql_print_error(ER(ER_CANT_OPEN_LIBRARY), tmp->dl, errno, dlerror());
/* Keep the udf in the hash so that we can remove it later */ /* Keep the udf in the hash so that we can remove it later */
continue; continue;
} }
...@@ -394,8 +401,13 @@ int mysql_create_function(THD *thd,udf_func *udf) ...@@ -394,8 +401,13 @@ int mysql_create_function(THD *thd,udf_func *udf)
Ensure that the .dll doesn't have a path Ensure that the .dll doesn't have a path
This is done to ensure that only approved dll from the system This is done to ensure that only approved dll from the system
directories are used (to make this even remotely secure). directories are used (to make this even remotely secure).
On windows we must check both FN_LIBCHAR and '/'.
*/ */
if (my_strchr(files_charset_info, udf->dl, udf->dl + strlen(udf->dl), FN_LIBCHAR)) if (my_strchr(files_charset_info, udf->dl,
udf->dl + strlen(udf->dl), FN_LIBCHAR) ||
IF_WIN(my_strchr(files_charset_info, udf->dl,
udf->dl + strlen(udf->dl), '/'), 0))
{ {
my_message(ER_UDF_NO_PATHS, ER(ER_UDF_NO_PATHS), MYF(0)); my_message(ER_UDF_NO_PATHS, ER(ER_UDF_NO_PATHS), MYF(0));
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -422,10 +434,12 @@ int mysql_create_function(THD *thd,udf_func *udf) ...@@ -422,10 +434,12 @@ int mysql_create_function(THD *thd,udf_func *udf)
} }
if (!(dl = find_udf_dl(udf->dl))) if (!(dl = find_udf_dl(udf->dl)))
{ {
if (!(dl = dlopen(udf->dl, RTLD_NOW))) char dlpath[FN_REFLEN];
strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", udf->dl, NullS);
if (!(dl = dlopen(dlpath, RTLD_NOW)))
{ {
DBUG_PRINT("error",("dlopen of %s failed, error: %d (%s)", DBUG_PRINT("error",("dlopen of %s failed, error: %d (%s)",
udf->dl, errno, dlerror())); udf->dl, errno, dlerror()));
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), my_error(ER_CANT_OPEN_LIBRARY, MYF(0),
udf->dl, errno, dlerror()); udf->dl, errno, dlerror());
goto err; goto err;
......
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