From 4c5dfc00f7a2ea3cf9475455e2749a96bfc38344 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 28 Apr 2011 12:22:41 +0300 Subject: Bug #11764517: 57359: POSSIBLE TO CIRCUMVENT SECURE_FILE_PRIV USING '..' ON WINDOWS Backport of the fix to 5.0 (to be null-merged to 5.1). Moved the test into the main test suite. Made mysql-test-run.pl to not use symlinks for sdtdata as the symlinks are now properly recognized by secure_file_priv. Made sure the paths in load_file(), LOAD DATA and SELECT .. INTO OUTFILE that are checked against secure_file_priv in a correct way similarly to 5.1 by the extended is_secure_file_path() backport before the comparison. Added an extensive test with all the variants of upper/lower case, slash/backslash and case sensitivity. Added few comments to the code. --- sql/mysqld.cc | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) (limited to 'sql/mysqld.cc') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f026bab1c32..3291085f380 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7855,6 +7855,64 @@ fn_format_relative_to_data_home(my_string to, const char *name, } +/** + Test a file path to determine if the path is compatible with the secure file + path restriction. + + @param path null terminated character string + + @return + @retval TRUE The path is secure + @retval FALSE The path isn't secure +*/ + +bool is_secure_file_path(char *path) +{ + char buff1[FN_REFLEN], buff2[FN_REFLEN]; + size_t opt_secure_file_priv_len; + /* + All paths are secure if opt_secure_file_path is 0 + */ + if (!opt_secure_file_priv) + return TRUE; + + opt_secure_file_priv_len= strlen(opt_secure_file_priv); + + if (strlen(path) >= FN_REFLEN) + return FALSE; + + if (my_realpath(buff1, path, 0)) + { + /* + The supplied file path might have been a file and not a directory. + */ + int length= (int) dirname_length(path); + if (length >= FN_REFLEN) + return FALSE; + memcpy(buff2, path, length); + buff2[length]= '\0'; + if (length == 0 || my_realpath(buff1, buff2, 0)) + return FALSE; + } + convert_dirname(buff2, buff1, NullS); + if (!lower_case_file_system) + { + if (strncmp(opt_secure_file_priv, buff2, opt_secure_file_priv_len)) + return FALSE; + } + else + { + if (files_charset_info->coll->strnncoll(files_charset_info, + (uchar *) buff2, strlen(buff2), + (uchar *) opt_secure_file_priv, + opt_secure_file_priv_len, + TRUE)) + return FALSE; + } + return TRUE; +} + + static void fix_paths(void) { char buff[FN_REFLEN],*pos; -- cgit v1.2.1 From 693fee5d561177e67223300015e5f16817c369e9 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 5 May 2011 12:10:49 +0300 Subject: Addendum 3 for bug #BUG#11764517 : expand secure_file_priv to the real patch so that it can later be compared with patchs with expanded symlinks --- sql/mysqld.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'sql/mysqld.cc') diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3291085f380..caeac5be100 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -7974,9 +7974,23 @@ static void fix_paths(void) */ if (opt_secure_file_priv) { - convert_dirname(buff, opt_secure_file_priv, NullS); - my_free(opt_secure_file_priv, MYF(0)); - opt_secure_file_priv= my_strdup(buff, MYF(MY_FAE)); + if (*opt_secure_file_priv == 0) + { + opt_secure_file_priv= 0; + } + else + { + if (strlen(opt_secure_file_priv) >= FN_REFLEN) + opt_secure_file_priv[FN_REFLEN-1]= '\0'; + if (my_realpath(buff, opt_secure_file_priv, 0)) + { + sql_print_warning("Failed to normalize the argument for --secure-file-priv."); + exit(1); + } + char *secure_file_real_path= (char *)my_malloc(FN_REFLEN, MYF(MY_FAE)); + convert_dirname(secure_file_real_path, buff, NullS); my_free(opt_secure_file_priv, MYF(0)); + opt_secure_file_priv= secure_file_real_path; + } } } -- cgit v1.2.1