diff options
author | Alexey Botchkov <holyfoot@mysql.com> | 2008-08-22 17:31:53 +0500 |
---|---|---|
committer | Alexey Botchkov <holyfoot@mysql.com> | 2008-08-22 17:31:53 +0500 |
commit | ec524d50a86b6fb75dc3dc5704fbed34568aa35c (patch) | |
tree | 7b2bfb5afa426b190c143d3fd42cdcf569c0ce2b /myisam | |
parent | de73b729543f40f46463c0134e380057ee4adb27 (diff) | |
download | mariadb-git-ec524d50a86b6fb75dc3dc5704fbed34568aa35c.tar.gz |
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
Diffstat (limited to 'myisam')
-rw-r--r-- | myisam/mi_check.c | 6 | ||||
-rw-r--r-- | myisam/mi_open.c | 42 | ||||
-rw-r--r-- | myisam/mi_static.c | 9 | ||||
-rw-r--r-- | myisam/myisamchk.c | 2 | ||||
-rw-r--r-- | myisam/myisamdef.h | 4 |
5 files changed, 50 insertions, 13 deletions
diff --git a/myisam/mi_check.c b/myisam/mi_check.c index daa5886f3ba..4f8883f377e 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -1732,7 +1732,7 @@ err: DATA_TMP_EXT, share->base.raid_chunks, (param->testflag & T_BACKUP_DATA ? MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || - mi_open_datafile(info,share,-1)) + mi_open_datafile(info,share,name,-1)) got_error=1; } } @@ -2519,7 +2519,7 @@ err: DATA_TMP_EXT, share->base.raid_chunks, (param->testflag & T_BACKUP_DATA ? MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || - mi_open_datafile(info,share,-1)) + mi_open_datafile(info,share,name,-1)) got_error=1; } } @@ -3050,7 +3050,7 @@ err: DATA_TMP_EXT, share->base.raid_chunks, (param->testflag & T_BACKUP_DATA ? MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || - mi_open_datafile(info,share,-1)) + mi_open_datafile(info,share,name,-1)) got_error=1; } } diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 6865708a941..8e2f61a3b4b 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -74,7 +74,7 @@ MI_INFO *test_if_reopen(char *filename) 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, key_parts,unique_key_parts,fulltext_keys,uniques; 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) head_length=sizeof(share_buff.state.header); 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); if (!(old_info=test_if_reopen(name_buff))) { @@ -463,7 +472,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) lock_error=1; /* Database unlocked */ } - if (mi_open_datafile(&info, share, -1)) + if (mi_open_datafile(&info, share, name, -1)) goto err; errpos=5; @@ -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 */ goto err; } - if (mi_open_datafile(&info, share, old_info->dfile)) + if (mi_open_datafile(&info, share, name, old_info->dfile)) goto err; errpos=5; 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 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 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->base.raid_type, share->base.raid_chunks, @@ -1205,8 +1232,7 @@ int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup __attr } else #endif - info->dfile=my_open(share->data_file_name, share->mode | O_SHARE, - MYF(MY_WME)); + info->dfile=my_open(data_name, share->mode | O_SHARE, MYF(MY_WME)); return info->dfile >= 0 ? 0 : 1; } diff --git a/myisam/mi_static.c b/myisam/mi_static.c index 21a25f66b7c..fb50eeb2fba 100644 --- a/myisam/mi_static.c +++ b/myisam/mi_static.c @@ -41,6 +41,15 @@ my_off_t myisam_max_temp_length= MAX_FILE_SIZE; ulong myisam_bulk_insert_tree_size=8192*1024; 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_ Position is , == , >= , <= , > , < diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index d421bbc92ed..29fb2ea1a60 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -1039,7 +1039,7 @@ static int myisamchk(MI_CHECK *param, my_string filename) error|=change_to_newfile(filename,MI_NAME_DEXT,DATA_TMP_EXT, raid_chunks, MYF(0)); - if (mi_open_datafile(info,info->s, -1)) + if (mi_open_datafile(info,info->s, NULL, -1)) error=1; param->out_flag&= ~O_NEW_DATA; /* We are using new datafile */ param->read_cache.file=info->dfile; diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 1a04cbe74fc..4ebd5648d26 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -739,7 +739,9 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); extern MI_INFO *test_if_reopen(char *filename); 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); void mi_setup_functions(register MYISAM_SHARE *share); |