summaryrefslogtreecommitdiff
path: root/mysql-test
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2017-02-15 18:45:19 +0100
committerSergei Golubchik <serg@mariadb.org>2017-02-27 12:35:10 +0100
commitb27fd90ad36f4194665744cc1dcdd05f2d0b47ef (patch)
treea48e90c7facfabf56074685a342fabf7584b8b48 /mysql-test
parentd78d0d459d10dd12069de82d6735f1acf183c631 (diff)
downloadmariadb-git-b27fd90ad36f4194665744cc1dcdd05f2d0b47ef.tar.gz
MDEV-11902 mi_open race condition
TOCTOU bug. The path is checked to be valid, symlinks are resolved. Then the resolved path is opened. Between the check and the open, there's a window when one can replace some path component with a symlink, bypassing validity checks. Fix: after we resolved all symlinks in the path, don't allow open() to resolve symlinks, there should be none. Compared to the old MyISAM/Aria code: * fastpath. Opening of not-symlinked files is just one open(), no fn_format() and lstat() anymore. * opening of symlinked tables doesn't do fn_format() and lstat() either. it also doesn't to realpath() (which was lstat-ing every path component), instead if opens every path component with O_PATH. * share->data_file_name stores realpath(path) not readlink(path). So, SHOW CREATE TABLE needs to do lstat/readlink() now (see ::info()), and certain error messages (cannot open file "XXX") show the real file path with all symlinks resolved.
Diffstat (limited to 'mysql-test')
-rw-r--r--mysql-test/r/symlink-aria-11902.result39
-rw-r--r--mysql-test/r/symlink-myisam-11902.result38
-rw-r--r--mysql-test/suite/federated/federated_bug_35333.result3
-rw-r--r--mysql-test/suite/federated/federated_bug_35333.test2
-rw-r--r--mysql-test/t/repair_symlink-5543.test4
-rw-r--r--mysql-test/t/symlink-aria-11902.test6
-rw-r--r--mysql-test/t/symlink-myisam-11902.test60
7 files changed, 146 insertions, 6 deletions
diff --git a/mysql-test/r/symlink-aria-11902.result b/mysql-test/r/symlink-aria-11902.result
new file mode 100644
index 00000000000..f704bb86ea7
--- /dev/null
+++ b/mysql-test/r/symlink-aria-11902.result
@@ -0,0 +1,39 @@
+set default_storage_engine=Aria;
+call mtr.add_suppression("File.*t1.* not found");
+create table mysql.t1 (a int, b char(16), index(a));
+insert mysql.t1 values (100, 'test'),(101,'test');
+create table t1 (a int, b char(16), index(a))
+data directory="MYSQLTEST_VARDIR/tmp/foo";
+insert t1 values (200, 'some'),(201,'some');
+select * from t1;
+a b
+200 some
+201 some
+flush tables;
+set debug_sync='mi_open_datafile SIGNAL ok WAIT_FOR go';
+select * from t1;
+set debug_sync='now WAIT_FOR ok';
+set debug_sync='now SIGNAL go';
+ERROR HY000: File 'MYSQLTEST_VARDIR/tmp/foo/t1.MAD' not found (Errcode: 20)
+flush tables;
+drop table if exists t1;
+create table t1 (a int, b char(16), index (a))
+index directory="MYSQLTEST_VARDIR/tmp/foo";
+insert t1 values (200, 'some'),(201,'some');
+explain select a from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 5 NULL 2 Using index
+select a from t1;
+a
+200
+201
+flush tables;
+set debug_sync='mi_open_kfile SIGNAL waiting WAIT_FOR run';
+select a from t1;
+set debug_sync='now WAIT_FOR waiting';
+set debug_sync='now SIGNAL run';
+ERROR HY000: Can't find file: 't1' (errno: 20)
+flush tables;
+drop table if exists t1;
+drop table mysql.t1;
+set debug_sync='RESET';
diff --git a/mysql-test/r/symlink-myisam-11902.result b/mysql-test/r/symlink-myisam-11902.result
new file mode 100644
index 00000000000..74785bbcdd1
--- /dev/null
+++ b/mysql-test/r/symlink-myisam-11902.result
@@ -0,0 +1,38 @@
+call mtr.add_suppression("File.*t1.* not found");
+create table mysql.t1 (a int, b char(16), index(a));
+insert mysql.t1 values (100, 'test'),(101,'test');
+create table t1 (a int, b char(16), index(a))
+data directory="MYSQLTEST_VARDIR/tmp/foo";
+insert t1 values (200, 'some'),(201,'some');
+select * from t1;
+a b
+200 some
+201 some
+flush tables;
+set debug_sync='mi_open_datafile SIGNAL ok WAIT_FOR go';
+select * from t1;
+set debug_sync='now WAIT_FOR ok';
+set debug_sync='now SIGNAL go';
+ERROR HY000: File 'MYSQLTEST_VARDIR/tmp/foo/t1.MYD' not found (Errcode: 20)
+flush tables;
+drop table if exists t1;
+create table t1 (a int, b char(16), index (a))
+index directory="MYSQLTEST_VARDIR/tmp/foo";
+insert t1 values (200, 'some'),(201,'some');
+explain select a from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL a 5 NULL 2 Using index
+select a from t1;
+a
+200
+201
+flush tables;
+set debug_sync='mi_open_kfile SIGNAL waiting WAIT_FOR run';
+select a from t1;
+set debug_sync='now WAIT_FOR waiting';
+set debug_sync='now SIGNAL run';
+ERROR HY000: Can't find file: 't1' (errno: 20)
+flush tables;
+drop table if exists t1;
+drop table mysql.t1;
+set debug_sync='RESET';
diff --git a/mysql-test/suite/federated/federated_bug_35333.result b/mysql-test/suite/federated/federated_bug_35333.result
index e1319cfeeae..c19fb78b7ae 100644
--- a/mysql-test/suite/federated/federated_bug_35333.result
+++ b/mysql-test/suite/federated/federated_bug_35333.result
@@ -27,9 +27,6 @@ TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE ROW_FORMAT TABLE_ROWS DATA_LENGTH TABL
test t1 BASE TABLE NULL NULL NULL NULL Can't find file: 't1' (errno: 2)
Warnings:
Warning 1017 Can't find file: 't1' (errno: 2)
-SHOW WARNINGS;
-Level Code Message
-Warning 1017 Can't find file: 't1' (errno: 2)
DROP TABLE t1;
ERROR 42S02: Unknown table 't1'
#
diff --git a/mysql-test/suite/federated/federated_bug_35333.test b/mysql-test/suite/federated/federated_bug_35333.test
index 6487e10e018..5134dbc6252 100644
--- a/mysql-test/suite/federated/federated_bug_35333.test
+++ b/mysql-test/suite/federated/federated_bug_35333.test
@@ -61,10 +61,10 @@ let $MYSQLD_DATADIR= `SELECT @@datadir`;
--echo #
--echo # Trigger a MyISAM system error during an INFORMATION_SCHEMA.TABLES query
--echo #
+--replace_result 20 2
SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, TABLE_ROWS, DATA_LENGTH, TABLE_COMMENT
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
-SHOW WARNINGS;
--disable_warnings
--error 1051
DROP TABLE t1;
diff --git a/mysql-test/t/repair_symlink-5543.test b/mysql-test/t/repair_symlink-5543.test
index bad65a4175a..6bdf72b4d40 100644
--- a/mysql-test/t/repair_symlink-5543.test
+++ b/mysql-test/t/repair_symlink-5543.test
@@ -9,7 +9,7 @@
eval create table t1 (a int) engine=myisam data directory='$MYSQL_TMP_DIR';
insert t1 values (1);
--system ln -s $MYSQL_TMP_DIR/foobar5543 $MYSQL_TMP_DIR/t1.TMD
---replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+--replace_regex / '.*\/t1/ 'MYSQL_TMP_DIR\/t1/
repair table t1;
drop table t1;
@@ -17,7 +17,7 @@ drop table t1;
eval create table t2 (a int) engine=aria data directory='$MYSQL_TMP_DIR';
insert t2 values (1);
--system ln -s $MYSQL_TMP_DIR/foobar5543 $MYSQL_TMP_DIR/t2.TMD
---replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
+--replace_regex / '.*\/t2/ 'MYSQL_TMP_DIR\/t2/
repair table t2;
drop table t2;
diff --git a/mysql-test/t/symlink-aria-11902.test b/mysql-test/t/symlink-aria-11902.test
new file mode 100644
index 00000000000..a2a266cbb25
--- /dev/null
+++ b/mysql-test/t/symlink-aria-11902.test
@@ -0,0 +1,6 @@
+#
+# MDEV-11902 mi_open race condition
+#
+source include/have_maria.inc;
+set default_storage_engine=Aria;
+source symlink-myisam-11902.test;
diff --git a/mysql-test/t/symlink-myisam-11902.test b/mysql-test/t/symlink-myisam-11902.test
new file mode 100644
index 00000000000..7e35ad117d0
--- /dev/null
+++ b/mysql-test/t/symlink-myisam-11902.test
@@ -0,0 +1,60 @@
+#
+# MDEV-11902 mi_open race condition
+#
+source include/have_debug_sync.inc;
+source include/have_symlink.inc;
+source include/not_windows.inc;
+call mtr.add_suppression("File.*t1.* not found");
+
+create table mysql.t1 (a int, b char(16), index(a));
+insert mysql.t1 values (100, 'test'),(101,'test');
+let $datadir=`select @@datadir`;
+
+exec mkdir $MYSQLTEST_VARDIR/tmp/foo;
+replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR;
+eval create table t1 (a int, b char(16), index(a))
+ data directory="$MYSQLTEST_VARDIR/tmp/foo";
+insert t1 values (200, 'some'),(201,'some');
+select * from t1;
+flush tables;
+set debug_sync='mi_open_datafile SIGNAL ok WAIT_FOR go';
+send select * from t1;
+connect con1, localhost, root;
+set debug_sync='now WAIT_FOR ok';
+exec rm -r $MYSQLTEST_VARDIR/tmp/foo;
+exec ln -s $datadir/mysql $MYSQLTEST_VARDIR/tmp/foo;
+set debug_sync='now SIGNAL go';
+connection default;
+replace_regex / '.*\/tmp\// 'MYSQLTEST_VARDIR\/tmp\// /31/20/;
+error 29;
+reap;
+flush tables;
+drop table if exists t1;
+exec rm -r $MYSQLTEST_VARDIR/tmp/foo;
+
+# same with INDEX DIRECTORY
+exec mkdir $MYSQLTEST_VARDIR/tmp/foo;
+replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR;
+eval create table t1 (a int, b char(16), index (a))
+ index directory="$MYSQLTEST_VARDIR/tmp/foo";
+insert t1 values (200, 'some'),(201,'some');
+explain select a from t1;
+select a from t1;
+flush tables;
+set debug_sync='mi_open_kfile SIGNAL waiting WAIT_FOR run';
+send select a from t1;
+connection con1;
+set debug_sync='now WAIT_FOR waiting';
+exec rm -r $MYSQLTEST_VARDIR/tmp/foo;
+exec ln -s $datadir/mysql $MYSQLTEST_VARDIR/tmp/foo;
+set debug_sync='now SIGNAL run';
+connection default;
+replace_regex / '.*\/tmp\// 'MYSQLTEST_VARDIR\/tmp\// /31/20/;
+error ER_FILE_NOT_FOUND;
+reap;
+flush tables;
+drop table if exists t1;
+exec rm -r $MYSQLTEST_VARDIR/tmp/foo;
+
+drop table mysql.t1;
+set debug_sync='RESET';