Commit 69657f97 authored by Alexey Botchkov's avatar Alexey Botchkov

Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.

            
            test_if_data_home_dir fixed to look into real path.
            Checks added to mi_open for symlinks into data home directory.

per-file messages:
        include/my_sys.h
          Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.
          
          my_is_symlink interface added
        include/myisam.h
          Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.
          
          myisam_test_invalid_symlink interface added
        myisam/mi_check.c
          Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.
          
          mi_open_datafile calls modified
        myisam/mi_open.c
          Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.
          
          code added to mi_open to check for symlinks into data home directory.
          mi_open_datafile now accepts 'original' file path to check if it's
          an allowed symlink.
        myisam/mi_static.c
          Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.
          
          myisam_test_invlaid_symlink defined
        myisam/myisamchk.c
          Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.
          
          mi_open_datafile call modified
        myisam/myisamdef.h
          Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.
          
          mi_open_datafile interface modified - 'real_path' parameter added
        mysql-test/r/symlink.test
          Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.
          
          error codes corrected as some patch now rejected pointing inside datahome
        mysql-test/r/symlink.result
          Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.
          
          error messages corrected in the result
        mysys/my_symlink.c
          Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.
          
          my_is_symlink() implementsd
          my_realpath() now returns the 'realpath' even if a file isn't a symlink
        sql/mysql_priv.h
          Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.
          
          test_if_data_home_dir interface
        sql/mysqld.cc
          Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.
          
          myisam_test_invalid_symlik set with the 'test_if_data_home_dir'
        sql/sql_parse.cc
          Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY.
          
          error messages corrected
          test_if_data_home_dir code fixed
parent 9bc9ddd5
...@@ -574,6 +574,7 @@ extern int my_close(File Filedes,myf MyFlags); ...@@ -574,6 +574,7 @@ extern int my_close(File Filedes,myf MyFlags);
extern File my_dup(File file, myf MyFlags); extern File my_dup(File file, myf MyFlags);
extern int my_mkdir(const char *dir, int Flags, myf MyFlags); extern int my_mkdir(const char *dir, int Flags, myf MyFlags);
extern int my_readlink(char *to, const char *filename, myf MyFlags); extern int my_readlink(char *to, const char *filename, myf MyFlags);
extern int my_is_symlink(const char *filename);
extern int my_realpath(char *to, const char *filename, myf MyFlags); extern int my_realpath(char *to, const char *filename, myf MyFlags);
extern File my_create_with_symlink(const char *linkname, const char *filename, extern File my_create_with_symlink(const char *linkname, const char *filename,
int createflags, int access_flags, int createflags, int access_flags,
......
...@@ -267,6 +267,10 @@ extern my_bool myisam_flush,myisam_delay_key_write,myisam_single_user; ...@@ -267,6 +267,10 @@ extern my_bool myisam_flush,myisam_delay_key_write,myisam_single_user;
extern my_off_t myisam_max_temp_length; extern my_off_t myisam_max_temp_length;
extern ulong myisam_bulk_insert_tree_size, myisam_data_pointer_size; extern ulong myisam_bulk_insert_tree_size, myisam_data_pointer_size;
/* usually used to check if a symlink points into the mysql data home */
/* which is normally forbidden */
extern int (*myisam_test_invalid_symlink)(const char *filename);
/* Prototypes for myisam-functions */ /* Prototypes for myisam-functions */
extern int mi_close(struct st_myisam_info *file); extern int mi_close(struct st_myisam_info *file);
......
...@@ -1732,7 +1732,7 @@ err: ...@@ -1732,7 +1732,7 @@ err:
DATA_TMP_EXT, share->base.raid_chunks, DATA_TMP_EXT, share->base.raid_chunks,
(param->testflag & T_BACKUP_DATA ? (param->testflag & T_BACKUP_DATA ?
MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
mi_open_datafile(info,share,-1)) mi_open_datafile(info,share,name,-1))
got_error=1; got_error=1;
} }
} }
...@@ -2519,7 +2519,7 @@ err: ...@@ -2519,7 +2519,7 @@ err:
DATA_TMP_EXT, share->base.raid_chunks, DATA_TMP_EXT, share->base.raid_chunks,
(param->testflag & T_BACKUP_DATA ? (param->testflag & T_BACKUP_DATA ?
MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
mi_open_datafile(info,share,-1)) mi_open_datafile(info,share,name,-1))
got_error=1; got_error=1;
} }
} }
...@@ -3050,7 +3050,7 @@ err: ...@@ -3050,7 +3050,7 @@ err:
DATA_TMP_EXT, share->base.raid_chunks, DATA_TMP_EXT, share->base.raid_chunks,
(param->testflag & T_BACKUP_DATA ? (param->testflag & T_BACKUP_DATA ?
MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
mi_open_datafile(info,share,-1)) mi_open_datafile(info,share,name,-1))
got_error=1; got_error=1;
} }
} }
......
...@@ -74,7 +74,7 @@ MI_INFO *test_if_reopen(char *filename) ...@@ -74,7 +74,7 @@ MI_INFO *test_if_reopen(char *filename)
MI_INFO *mi_open(const char *name, int mode, uint open_flags) MI_INFO *mi_open(const char *name, int mode, uint open_flags)
{ {
int lock_error,kfile,open_mode,save_errno,have_rtree=0; int lock_error,kfile,open_mode,save_errno,have_rtree=0, realpath_err;
uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys, uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys,
key_parts,unique_key_parts,fulltext_keys,uniques; key_parts,unique_key_parts,fulltext_keys,uniques;
char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN], char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN],
...@@ -94,7 +94,16 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -94,7 +94,16 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
head_length=sizeof(share_buff.state.header); head_length=sizeof(share_buff.state.header);
bzero((byte*) &info,sizeof(info)); bzero((byte*) &info,sizeof(info));
my_realpath(name_buff, fn_format(org_name,name,"",MI_NAME_IEXT,4),MYF(0)); realpath_err= my_realpath(name_buff,
fn_format(org_name,name,"",MI_NAME_IEXT,4),MYF(0));
if (my_is_symlink(org_name) &&
(realpath_err || (*myisam_test_invalid_symlink)(name_buff)))
{
my_errno= HA_WRONG_CREATE_OPTION;
DBUG_RETURN (NULL);
}
pthread_mutex_lock(&THR_LOCK_myisam); pthread_mutex_lock(&THR_LOCK_myisam);
if (!(old_info=test_if_reopen(name_buff))) if (!(old_info=test_if_reopen(name_buff)))
{ {
...@@ -463,7 +472,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -463,7 +472,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
lock_error=1; /* Database unlocked */ lock_error=1; /* Database unlocked */
} }
if (mi_open_datafile(&info, share, -1)) if (mi_open_datafile(&info, share, name, -1))
goto err; goto err;
errpos=5; errpos=5;
...@@ -534,7 +543,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -534,7 +543,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
my_errno=EACCES; /* Can't open in write mode */ my_errno=EACCES; /* Can't open in write mode */
goto err; goto err;
} }
if (mi_open_datafile(&info, share, old_info->dfile)) if (mi_open_datafile(&info, share, name, old_info->dfile))
goto err; goto err;
errpos=5; errpos=5;
have_rtree= old_info->rtree_recursion_state != NULL; have_rtree= old_info->rtree_recursion_state != NULL;
...@@ -1191,12 +1200,30 @@ The argument file_to_dup is here for the future if there would on some OS ...@@ -1191,12 +1200,30 @@ The argument file_to_dup is here for the future if there would on some OS
exist a dup()-like call that would give us two different file descriptors. exist a dup()-like call that would give us two different file descriptors.
*************************************************************************/ *************************************************************************/
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup __attribute__((unused))) int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *org_name,
File file_to_dup __attribute__((unused)))
{ {
char *data_name= share->data_file_name;
char real_data_name[FN_REFLEN];
if (org_name)
{
fn_format(real_data_name,org_name,"",MI_NAME_DEXT,4);
if (my_is_symlink(real_data_name))
{
if (my_realpath(real_data_name, real_data_name, MYF(0)) ||
(*myisam_test_invalid_symlink)(real_data_name))
{
my_errno= HA_WRONG_CREATE_OPTION;
return 1;
}
data_name= real_data_name;
}
}
#ifdef USE_RAID #ifdef USE_RAID
if (share->base.raid_type) if (share->base.raid_type)
{ {
info->dfile=my_raid_open(share->data_file_name, info->dfile=my_raid_open(data_name,
share->mode | O_SHARE, share->mode | O_SHARE,
share->base.raid_type, share->base.raid_type,
share->base.raid_chunks, share->base.raid_chunks,
...@@ -1205,8 +1232,7 @@ int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup __attr ...@@ -1205,8 +1232,7 @@ int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup __attr
} }
else else
#endif #endif
info->dfile=my_open(share->data_file_name, share->mode | O_SHARE, info->dfile=my_open(data_name, share->mode | O_SHARE, MYF(MY_WME));
MYF(MY_WME));
return info->dfile >= 0 ? 0 : 1; return info->dfile >= 0 ? 0 : 1;
} }
......
...@@ -41,6 +41,15 @@ my_off_t myisam_max_temp_length= MAX_FILE_SIZE; ...@@ -41,6 +41,15 @@ my_off_t myisam_max_temp_length= MAX_FILE_SIZE;
ulong myisam_bulk_insert_tree_size=8192*1024; ulong myisam_bulk_insert_tree_size=8192*1024;
ulong myisam_data_pointer_size=4; ulong myisam_data_pointer_size=4;
static int always_valid(const char *filename)
{
return 0;
}
int (*myisam_test_invalid_symlink)(const char *filename)= always_valid;
/* /*
read_vec[] is used for converting between P_READ_KEY.. and SEARCH_ read_vec[] is used for converting between P_READ_KEY.. and SEARCH_
Position is , == , >= , <= , > , < Position is , == , >= , <= , > , <
......
...@@ -1039,7 +1039,7 @@ static int myisamchk(MI_CHECK *param, my_string filename) ...@@ -1039,7 +1039,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
error|=change_to_newfile(filename,MI_NAME_DEXT,DATA_TMP_EXT, error|=change_to_newfile(filename,MI_NAME_DEXT,DATA_TMP_EXT,
raid_chunks, raid_chunks,
MYF(0)); MYF(0));
if (mi_open_datafile(info,info->s, -1)) if (mi_open_datafile(info,info->s, NULL, -1))
error=1; error=1;
param->out_flag&= ~O_NEW_DATA; /* We are using new datafile */ param->out_flag&= ~O_NEW_DATA; /* We are using new datafile */
param->read_cache.file=info->dfile; param->read_cache.file=info->dfile;
......
...@@ -739,7 +739,9 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); ...@@ -739,7 +739,9 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows);
extern MI_INFO *test_if_reopen(char *filename); extern MI_INFO *test_if_reopen(char *filename);
my_bool check_table_is_closed(const char *name, const char *where); my_bool check_table_is_closed(const char *name, const char *where);
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup); int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *orn_name,
File file_to_dup);
int mi_open_keyfile(MYISAM_SHARE *share); int mi_open_keyfile(MYISAM_SHARE *share);
void mi_setup_functions(register MYISAM_SHARE *share); void mi_setup_functions(register MYISAM_SHARE *share);
......
...@@ -71,7 +71,7 @@ drop table t1; ...@@ -71,7 +71,7 @@ drop table t1;
SHOW CREATE TABLE t9; SHOW CREATE TABLE t9;
disable_query_log; disable_query_log;
--error 1103,1103 --error 1210, 1210
create table t1 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="tmp"; create table t1 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="tmp";
# Check that we cannot link over a table from another database. # Check that we cannot link over a table from another database.
...@@ -81,7 +81,7 @@ create database mysqltest; ...@@ -81,7 +81,7 @@ create database mysqltest;
--error 1,1 --error 1,1
create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="/this-dir-does-not-exist"; create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="/this-dir-does-not-exist";
--error 1103,1103 --error 1210, 1210
create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="not-hard-path"; create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="not-hard-path";
# Should fail becasue the file t9.MYI already exist in 'run' # Should fail becasue the file t9.MYI already exist in 'run'
......
...@@ -106,38 +106,39 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags) ...@@ -106,38 +106,39 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags)
#define BUFF_LEN FN_LEN #define BUFF_LEN FN_LEN
#endif #endif
int my_is_symlink(const char *filename __attribute__((unused)))
{
struct stat stat_buff;
return !lstat(filename, &stat_buff) && S_ISLNK(stat_buff.st_mode);
}
int my_realpath(char *to, const char *filename, int my_realpath(char *to, const char *filename,
myf MyFlags __attribute__((unused))) myf MyFlags __attribute__((unused)))
{ {
#if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH) #if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH)
int result=0; int result=0;
char buff[BUFF_LEN]; char buff[BUFF_LEN];
struct stat stat_buff; char *ptr;
DBUG_ENTER("my_realpath"); DBUG_ENTER("my_realpath");
if (!(MyFlags & MY_RESOLVE_LINK) || DBUG_PRINT("info",("executing realpath"));
(!lstat(filename,&stat_buff) && S_ISLNK(stat_buff.st_mode))) if ((ptr=realpath(filename,buff)))
{
char *ptr;
DBUG_PRINT("info",("executing realpath"));
if ((ptr=realpath(filename,buff)))
{
strmake(to,ptr,FN_REFLEN-1); strmake(to,ptr,FN_REFLEN-1);
} else
else {
{ /*
/* Realpath didn't work; Use my_load_path() which is a poor substitute
Realpath didn't work; Use my_load_path() which is a poor substitute original name but will at least be able to resolve paths that starts
original name but will at least be able to resolve paths that starts with '.'.
with '.'. */
*/ DBUG_PRINT("error",("realpath failed with errno: %d", errno));
DBUG_PRINT("error",("realpath failed with errno: %d", errno)); my_errno=errno;
my_errno=errno; if (MyFlags & MY_WME)
if (MyFlags & MY_WME) my_error(EE_REALPATH, MYF(0), filename, my_errno);
my_error(EE_REALPATH, MYF(0), filename, my_errno); my_load_path(to, filename, NullS);
my_load_path(to, filename, NullS); result= -1;
result= -1;
}
} }
DBUG_RETURN(result); DBUG_RETURN(result);
#else #else
......
...@@ -1264,6 +1264,7 @@ extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH], ...@@ -1264,6 +1264,7 @@ extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH],
mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[], mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[],
mysql_unpacked_real_data_home[], mysql_unpacked_real_data_home[],
def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
extern int mysql_unpacked_real_data_home_len;
#define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list)) #define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list))
extern MY_TMPDIR mysql_tmpdir_list; extern MY_TMPDIR mysql_tmpdir_list;
extern const char *command_name[]; extern const char *command_name[];
...@@ -1764,6 +1765,8 @@ inline void kill_delayed_threads(void) {} ...@@ -1764,6 +1765,8 @@ inline void kill_delayed_threads(void) {}
#define check_stack_overrun(A, B, C) 0 #define check_stack_overrun(A, B, C) 0
#endif #endif
extern "C" int test_if_data_home_dir(const char *dir);
#endif /* MYSQL_CLIENT */ #endif /* MYSQL_CLIENT */
#endif #endif
...@@ -477,6 +477,7 @@ char mysql_real_data_home[FN_REFLEN], ...@@ -477,6 +477,7 @@ char mysql_real_data_home[FN_REFLEN],
*opt_init_file, *opt_tc_log_file, *opt_init_file, *opt_tc_log_file,
mysql_unpacked_real_data_home[FN_REFLEN], mysql_unpacked_real_data_home[FN_REFLEN],
def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
int mysql_unpacked_real_data_home_len;
char *mysql_data_home= mysql_real_data_home; char *mysql_data_home= mysql_real_data_home;
const key_map key_map_empty(0); const key_map key_map_empty(0);
key_map key_map_full(0); // Will be initialized later key_map key_map_full(0); // Will be initialized later
...@@ -6696,6 +6697,7 @@ static void mysql_init_variables(void) ...@@ -6696,6 +6697,7 @@ static void mysql_init_variables(void)
/* Things reset to zero */ /* Things reset to zero */
opt_skip_slave_start= opt_reckless_slave = 0; opt_skip_slave_start= opt_reckless_slave = 0;
mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0; mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
myisam_test_invalid_symlink= test_if_data_home_dir;
opt_log= opt_slow_log= 0; opt_log= opt_slow_log= 0;
opt_update_log= 0; opt_update_log= 0;
opt_bin_log= 0; opt_bin_log= 0;
...@@ -7746,9 +7748,12 @@ static void fix_paths(void) ...@@ -7746,9 +7748,12 @@ static void fix_paths(void)
pos[1]= 0; pos[1]= 0;
} }
convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS); convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
(void) fn_format(buff, mysql_real_data_home, "", "", my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0));
(MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS)); mysql_unpacked_real_data_home_len= strlen(mysql_unpacked_real_data_home);
(void) unpack_dirname(mysql_unpacked_real_data_home, buff); if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len-1] == FN_LIBCHAR)
--mysql_unpacked_real_data_home_len;
convert_dirname(language,language,NullS); convert_dirname(language,language,NullS);
(void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir (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); (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
......
...@@ -76,7 +76,6 @@ static void remove_escape(char *name); ...@@ -76,7 +76,6 @@ static void remove_escape(char *name);
static bool append_file_to_dir(THD *thd, const char **filename_ptr, static bool append_file_to_dir(THD *thd, const char **filename_ptr,
const char *table_name); const char *table_name);
static bool check_show_create_table_access(THD *thd, TABLE_LIST *table); static bool check_show_create_table_access(THD *thd, TABLE_LIST *table);
static bool test_if_data_home_dir(const char *dir);
const char *any_db="*any*"; // Special symbol for check_access const char *any_db="*any*"; // Special symbol for check_access
...@@ -3044,13 +3043,13 @@ mysql_execute_command(THD *thd) ...@@ -3044,13 +3043,13 @@ mysql_execute_command(THD *thd)
if (test_if_data_home_dir(lex->create_info.data_file_name)) if (test_if_data_home_dir(lex->create_info.data_file_name))
{ {
my_error(ER_WRONG_ARGUMENTS,MYF(0),"DATA DIRECORY"); my_error(ER_WRONG_ARGUMENTS,MYF(0),"DATA DIRECTORY");
res= -1; res= -1;
break; break;
} }
if (test_if_data_home_dir(lex->create_info.index_file_name)) if (test_if_data_home_dir(lex->create_info.index_file_name))
{ {
my_error(ER_WRONG_ARGUMENTS,MYF(0),"INDEX DIRECORY"); my_error(ER_WRONG_ARGUMENTS,MYF(0),"INDEX DIRECTORY");
res= -1; res= -1;
break; break;
} }
...@@ -7946,10 +7945,12 @@ bool check_string_length(LEX_STRING *str, const char *err_msg, ...@@ -7946,10 +7945,12 @@ bool check_string_length(LEX_STRING *str, const char *err_msg,
1 error 1 error
*/ */
static bool test_if_data_home_dir(const char *dir) C_MODE_START
int test_if_data_home_dir(const char *dir)
{ {
char path[FN_REFLEN], conv_path[FN_REFLEN]; char path[FN_REFLEN];
uint dir_len, home_dir_len= strlen(mysql_unpacked_real_data_home); uint dir_len;
DBUG_ENTER("test_if_data_home_dir"); DBUG_ENTER("test_if_data_home_dir");
if (!dir) if (!dir)
...@@ -7957,21 +7958,27 @@ static bool test_if_data_home_dir(const char *dir) ...@@ -7957,21 +7958,27 @@ static bool test_if_data_home_dir(const char *dir)
(void) fn_format(path, dir, "", "", (void) fn_format(path, dir, "", "",
(MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS)); (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS));
dir_len= unpack_dirname(conv_path, dir); dir_len= strlen(path);
if (mysql_unpacked_real_data_home_len<= dir_len)
if (home_dir_len <= dir_len)
{ {
if (dir_len > mysql_unpacked_real_data_home_len &&
path[mysql_unpacked_real_data_home_len] != FN_LIBCHAR)
DBUG_RETURN(0);
if (lower_case_file_system) if (lower_case_file_system)
{ {
if (!my_strnncoll(default_charset_info, (const uchar*) conv_path, if (!my_strnncoll(default_charset_info, (const uchar*) path,
home_dir_len, mysql_unpacked_real_data_home_len,
(const uchar*) mysql_unpacked_real_data_home, (const uchar*) mysql_unpacked_real_data_home,
home_dir_len)) mysql_unpacked_real_data_home_len))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
else if (!memcmp(conv_path, mysql_unpacked_real_data_home, home_dir_len)) else if (!memcmp(path, mysql_unpacked_real_data_home,
mysql_unpacked_real_data_home_len))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
DBUG_RETURN(0); DBUG_RETURN(0);
} }
C_MODE_END
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