tags 480292 +patch quit Here's a patch I'm building for an Etch update to address the problem. It's pretty close to the same one used in the first fix to this bug, except that it adds a call to realpath() to resolve all components of the path, and fixes the argument passing so as not to throw the resolved forms away.
-- Devin \ aqua(at)devin.com, IRC:Requiem; http://www.devin.com Carraway \ 1024D/E9ABFCD2: 13E7 199E DD1E 65F0 8905 2E43 5395 CA0D E9AB FCD2
#! /bin/sh /usr/share/dpatch/dpatch-run ## 97_SECURITY_CVE-2008-2079.dpatch by <[EMAIL PROTECTED]> ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Fix for CVE-2008-2079: Some access checks could be bypassed by local ## DP: users creating tables with chosen data or index directory arguments ## DP: later reused by subsequently created tables. @DPATCH@ diff -aruN mysql-dfsg-5.0-5.0.32.orig/sql/mysql_priv.h mysql-dfsg-5.0-5.0.32/sql/mysql_priv.h --- mysql-dfsg-5.0-5.0.32.orig/sql/mysql_priv.h 2008-07-06 13:09:21.000000000 -0700 +++ mysql-dfsg-5.0-5.0.32/sql/mysql_priv.h 2008-07-06 13:13:21.000000000 -0700 @@ -1193,6 +1193,7 @@ extern time_t start_time; extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH], mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[], + mysql_unpacked_real_data_home[], def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; #define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list)) extern MY_TMPDIR mysql_tmpdir_list; diff -aruN mysql-dfsg-5.0-5.0.32.orig/sql/mysqld.cc mysql-dfsg-5.0-5.0.32/sql/mysqld.cc --- mysql-dfsg-5.0-5.0.32.orig/sql/mysqld.cc 2006-12-20 03:14:10.000000000 -0800 +++ mysql-dfsg-5.0-5.0.32/sql/mysqld.cc 2008-07-06 13:13:21.000000000 -0700 @@ -437,14 +437,13 @@ char mysql_real_data_home[FN_REFLEN], language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], *opt_init_file, *opt_tc_log_file, + mysql_unpacked_real_data_home[FN_REFLEN], def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; - +char *mysql_data_home= mysql_real_data_home; const key_map key_map_empty(0); key_map key_map_full(0); // Will be initialized later const char *opt_date_time_formats[3]; - -char *mysql_data_home= mysql_real_data_home; char server_version[SERVER_VERSION_LENGTH]; char *mysqld_unix_port, *opt_mysql_tmpdir; const char **errmesg; /* Error messages */ @@ -7356,6 +7355,9 @@ pos[1]= 0; } convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS); + (void) fn_format(buff, mysql_real_data_home, "", "", + (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS)); + (void) unpack_dirname(mysql_unpacked_real_data_home, buff); convert_dirname(language,language,NullS); (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); diff -aruN mysql-dfsg-5.0-5.0.32.orig/sql/sql_parse.cc mysql-dfsg-5.0-5.0.32/sql/sql_parse.cc --- mysql-dfsg-5.0-5.0.32.orig/sql/sql_parse.cc 2008-07-06 13:09:21.000000000 -0700 +++ mysql-dfsg-5.0-5.0.32/sql/sql_parse.cc 2008-07-06 13:18:30.000000000 -0700 @@ -76,6 +76,7 @@ static void remove_escape(char *name); static bool append_file_to_dir(THD *thd, const char **filename_ptr, const char *table_name); +static bool test_if_data_home_dir(const char *dir); static bool check_show_create_table_access(THD *thd, TABLE_LIST *table); const char *any_db="*any*"; // Special symbol for check_access @@ -2890,6 +2891,20 @@ #ifndef HAVE_READLINK lex->create_info.data_file_name=lex->create_info.index_file_name=0; #else + + if (test_if_data_home_dir(lex->create_info.data_file_name)) + { + my_error(ER_WRONG_ARGUMENTS,MYF(0),"DATA DIRECORY"); + res= -1; + break; + } + if (test_if_data_home_dir(lex->create_info.index_file_name)) + { + my_error(ER_WRONG_ARGUMENTS,MYF(0),"INDEX DIRECORY"); + res= -1; + break; + } + /* Fix names if symlinked tables */ if (append_file_to_dir(thd, &lex->create_info.data_file_name, create_table->table_name) || @@ -7664,3 +7679,50 @@ return TRUE; } + + +/* + Check if path does not contain mysql data home directory + + SYNOPSIS + test_if_data_home_dir() + dir directory + conv_home_dir converted data home directory + home_dir_len converted data home directory length + + RETURN VALUES + 0 ok + 1 error +*/ + +static bool test_if_data_home_dir(const char *dir) +{ + char path[FN_REFLEN], conv_path[PATH_MAX+1], real_path[PATH_MAX+1]; + uint dir_len, home_dir_len= strlen(mysql_unpacked_real_data_home); + DBUG_ENTER("test_if_data_home_dir"); + + if (!dir) + DBUG_RETURN(0); + + (void) fn_format(path, dir, "", "", + (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS)); + if (!realpath(path, real_path)) + DBUG_RETURN(1); + dir_len= unpack_dirname(conv_path, real_path); + + if (home_dir_len <= dir_len) + { + if (lower_case_file_system) + { + if (!my_strnncoll(default_charset_info, (const uchar*) conv_path, + home_dir_len, + (const uchar*) mysql_unpacked_real_data_home, + home_dir_len)) + DBUG_RETURN(1); + } + else if (!memcmp(conv_path, mysql_unpacked_real_data_home, home_dir_len)) + DBUG_RETURN(1); + } + DBUG_RETURN(0); +} +
signature.asc
Description: Digital signature