Commit bf1887fa authored by Kristofer Pettersson's avatar Kristofer Pettersson

Bug#50373 --secure-file-priv=""

Iterative patch improvement. Previously committed patch
caused wrong result on Windows. The previous patch also
broke secure_file_priv for symlinks since not all file
paths which must be compared against this variable are
normalized using the same norm.

The server variable opt_secure_file_priv wasn't
normalized properly and caused the operations
LOAD DATA INFILE .. INTO TABLE ..
and
SELECT load_file(..)
to do different interpretations of the 
--secure-file-priv option.
     
The patch moves code to the server initialization
routines so that the path always is normalized
once and only once.
      
It was also intended that setting the option
to an empty string should be equal to 
lifting all previously set restrictions. This
is also fixed by this patch.


mysql-test/r/loaddata.result:
  * Removed test code which will currently break the much used --mem feature of mtr.
mysql-test/t/loaddata.test:
  * Removed test code which will currently break the much used --mem feature of mtr.
sql/item_strfunc.cc:
  * Replaced string comparing code on opt_secure_file_priv with an interface which guarantees that both file paths are normalized using the same norm on all platforms.
sql/mysql_priv.h:
  * Added signature for is_secure_file_path()
sql/mysqld.cc:
  * New function for checking if a path compatible with the secure path restriction.
  * Added initialization of the opt_secure_file_priv variable.
sql/sql_class.cc:
  * Replaced string comparing code on opt_secure_file_priv with an interface which guarantees that both file paths are normalized using the same norm on all platforms.
sql/sql_load.cc:
  * Replaced string comparing code on opt_secure_file_priv with an interface which guarantees that both file paths are normalized using the same norm on all platforms.
parent 9dca1273
...@@ -202,12 +202,6 @@ select * from t1; ...@@ -202,12 +202,6 @@ select * from t1;
a b c a b c
10 NULL Ten 10 NULL Ten
15 NULL Fifteen 15 NULL Fifteen
show variables like "secure_file_pri%";
Variable_name Value
secure_file_priv MYSQLTEST_VARDIR
select @@secure_file_priv;
@@secure_file_priv
MYSQLTEST_VARDIR
set @@secure_file_priv= 0; set @@secure_file_priv= 0;
ERROR HY000: Variable 'secure_file_priv' is a read only variable ERROR HY000: Variable 'secure_file_priv' is a read only variable
truncate table t1; truncate table t1;
......
...@@ -153,10 +153,16 @@ select * from t1; ...@@ -153,10 +153,16 @@ select * from t1;
# #
# It should not be possible to load from a file outside of vardir # It should not be possible to load from a file outside of vardir
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ## The following lines were disabled because of patch for
show variables like "secure_file_pri%"; ## bug 50373. MYSQLTEST_VARDIR doesn't rewrite symlinks
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ## to real paths, but this is done for secure_file_priv.
select @@secure_file_priv; ## Because of this the result can't be replaced if the
## test suite runs with the --mem option which creates
## symlinks to the ramdisk.
#--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
#show variables like "secure_file_pri%";
#--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
#select @@secure_file_priv;
--error 1238 --error 1238
set @@secure_file_priv= 0; set @@secure_file_priv= 0;
......
...@@ -2959,8 +2959,7 @@ String *Item_load_file::val_str(String *str) ...@@ -2959,8 +2959,7 @@ String *Item_load_file::val_str(String *str)
MY_RELATIVE_PATH | MY_UNPACK_FILENAME); MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
/* Read only allowed from within dir specified by secure_file_priv */ /* Read only allowed from within dir specified by secure_file_priv */
if (opt_secure_file_priv && if (!is_secure_file_path(path))
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
goto err; goto err;
if (!my_stat(path, &stat_info, MYF(0))) if (!my_stat(path, &stat_info, MYF(0)))
......
...@@ -1832,6 +1832,12 @@ void sql_perror(const char *message); ...@@ -1832,6 +1832,12 @@ void sql_perror(const char *message);
bool fn_format_relative_to_data_home(char * to, const char *name, bool fn_format_relative_to_data_home(char * to, const char *name,
const char *dir, const char *extension); const char *dir, const char *extension);
/**
Test a file path to determine if the path is compatible with the secure file
path restriction.
*/
bool is_secure_file_path(char *path);
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
File open_binlog(IO_CACHE *log, const char *log_file_name, File open_binlog(IO_CACHE *log, const char *log_file_name,
const char **errmsg); const char **errmsg);
......
...@@ -8776,6 +8776,45 @@ fn_format_relative_to_data_home(char * to, const char *name, ...@@ -8776,6 +8776,45 @@ fn_format_relative_to_data_home(char * 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];
/*
All paths are secure if opt_secure_file_path is 0
*/
if (!opt_secure_file_priv)
return TRUE;
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 (strncmp(opt_secure_file_priv, buff2, strlen(opt_secure_file_priv)))
return FALSE;
return TRUE;
}
static int fix_paths(void) static int fix_paths(void)
{ {
char buff[FN_REFLEN],*pos; char buff[FN_REFLEN],*pos;
...@@ -8843,14 +8882,13 @@ static int fix_paths(void) ...@@ -8843,14 +8882,13 @@ static int fix_paths(void)
} }
else else
{ {
convert_dirname(buff, opt_secure_file_priv, NullS); if (my_realpath(buff, opt_secure_file_priv, 0))
char *secure_file_real_path= (char *)my_malloc(FN_REFLEN, MYF(MY_FAE));
if (secure_file_real_path == 0 ||
my_realpath(secure_file_real_path, buff, 0))
{ {
sql_print_warning("Failed to normalize the argument for --secure-file-priv."); sql_print_warning("Failed to normalize the argument for --secure-file-priv.");
return 1; return 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)); my_free(opt_secure_file_priv, MYF(0));
opt_secure_file_priv= secure_file_real_path; opt_secure_file_priv= secure_file_real_path;
} }
......
...@@ -1831,8 +1831,7 @@ static File create_file(THD *thd, char *path, sql_exchange *exchange, ...@@ -1831,8 +1831,7 @@ static File create_file(THD *thd, char *path, sql_exchange *exchange,
else else
(void) fn_format(path, exchange->file_name, mysql_real_data_home, "", option); (void) fn_format(path, exchange->file_name, mysql_real_data_home, "", option);
if (opt_secure_file_priv && if (!is_secure_file_path(path))
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
{ {
/* Write only allowed to dir or subdir specified by secure_file_priv */ /* Write only allowed to dir or subdir specified by secure_file_priv */
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv"); my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
......
...@@ -348,14 +348,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -348,14 +348,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
DBUG_ASSERT(FALSE); DBUG_ASSERT(FALSE);
#endif #endif
} }
else if (opt_secure_file_priv) else if (!is_secure_file_path(name))
{ {
if (strncmp(opt_secure_file_priv, name, strlen(opt_secure_file_priv))) /* Read only allowed from within dir specified by secure_file_priv */
{ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
/* Read only allowed from within dir specified by secure_file_priv */ DBUG_RETURN(TRUE);
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
DBUG_RETURN(TRUE);
}
} }
} }
......
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