1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

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''
This commit is contained in:
unknown
2007-05-18 16:23:46 +05:00
parent 0ea67375ef
commit 7839da601c
5 changed files with 30 additions and 28 deletions

View File

@ -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 () {
# ---------------------------------------------------- # ----------------------------------------------------
$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 ($$$$) {
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
{ {

View File

@ -1,6 +1,7 @@
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';

View File

@ -0,0 +1 @@
$EXAMPLE_PLUGIN_OPT

View File

@ -0,0 +1 @@
$UDF_EXAMPLE_LIB_OPT

View File

@ -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()
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)
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)
} }
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;