diff options
-rw-r--r-- | mysql-test/r/symlink.result | 6 | ||||
-rw-r--r-- | mysql-test/t/symlink.test | 12 | ||||
-rw-r--r-- | mysys/my_symlink2.c | 11 |
3 files changed, 28 insertions, 1 deletions
diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index 18299bf4298..8978eee89c3 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -99,6 +99,12 @@ t1 CREATE TABLE `t1` ( `b` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +CREATE TABLE t1(a INT) +DATA DIRECTORY='TEST_DIR/var/master-data/mysql' +INDEX DIRECTORY='TEST_DIR/var/master-data/mysql'; +RENAME TABLE t1 TO user; +ERROR HY000: Can't create/write to file 'TEST_DIR/var/master-data/mysql/user.MYI' (Errcode: 17) +DROP TABLE t1; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 8c67a4c1048..21c17cfb45e 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -125,6 +125,18 @@ show create table t1; drop table t1; # +# BUG#32111 - Security Breach via DATA/INDEX DIRECORY and RENAME TABLE +# +--replace_result $MYSQL_TEST_DIR TEST_DIR +eval CREATE TABLE t1(a INT) +DATA DIRECTORY='$MYSQL_TEST_DIR/var/master-data/mysql' +INDEX DIRECTORY='$MYSQL_TEST_DIR/var/master-data/mysql'; +--replace_result $MYSQL_TEST_DIR TEST_DIR +--error 1 +RENAME TABLE t1 TO user; +DROP TABLE t1; + +# # Test specifying DATA DIRECTORY that is the same as what would normally # have been chosen. (Bug #8707) # diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c index e2493874097..ee0a45cf93b 100644 --- a/mysys/my_symlink2.c +++ b/mysys/my_symlink2.c @@ -126,6 +126,7 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) int was_symlink= (!my_disable_symlinks && !my_readlink(link_name, from, MYF(0))); int result=0; + int name_is_different; DBUG_ENTER("my_rename_with_symlink"); if (!was_symlink) @@ -134,6 +135,14 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) /* Change filename that symlink pointed to */ strmov(tmp_name, to); fn_same(tmp_name,link_name,1); /* Copy dir */ + name_is_different= strcmp(link_name, tmp_name); + if (name_is_different && !access(tmp_name, F_OK)) + { + my_errno= EEXIST; + if (MyFlags & MY_WME) + my_error(EE_CANTCREATEFILE, MYF(0), tmp_name, EEXIST); + DBUG_RETURN(1); + } /* Create new symlink */ if (my_symlink(tmp_name, to, MyFlags)) @@ -145,7 +154,7 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) the same basename and different directories. */ - if (strcmp(link_name, tmp_name) && my_rename(link_name, tmp_name, MyFlags)) + if (name_is_different && my_rename(link_name, tmp_name, MyFlags)) { int save_errno=my_errno; my_delete(to, MyFlags); /* Remove created symlink */ |