summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <gluh@mysql.com/eagle.(none)>2008-02-29 13:55:00 +0400
committerunknown <gluh@mysql.com/eagle.(none)>2008-02-29 13:55:00 +0400
commitab6042590186ad14bbd73a64f5d1f3f77223bdb3 (patch)
treec3795dc2bf7c70e1a1d2c17e954f6b8e7aa42593
parentf364c09901440384e48264a838750243de0fab0e (diff)
downloadmariadb-git-ab6042590186ad14bbd73a64f5d1f3f77223bdb3.tar.gz
Bug#32167 another privilege bypass with DATA/INDEX DIRECORY(ver 4.1,5.0)
added new function test_if_data_home_dir() which checks that path does not contain mysql data home directory. Using of mysql data home directory in DATA DIRECTORY & INDEX DIRECTORY is disallowed. mysql-test/r/symlink.result: test result mysql-test/t/symlink.test: test case sql/mysql_priv.h: new variable mysql_unpacked_real_data_home sql/mysqld.cc: new variable mysql_unpacked_real_data_home sql/sql_parse.cc: added new function test_if_data_home_dir() which checks that path does not contain mysql data home directory. Using of mysql data home directory in DATA DIRECTORY & INDEX DIRECTORY is disallowed.
-rw-r--r--mysql-test/r/symlink.result38
-rw-r--r--mysql-test/t/symlink.test48
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/mysqld.cc4
-rw-r--r--sql/sql_parse.cc61
5 files changed, 115 insertions, 37 deletions
diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result
index 32dc72b8219..84d7d8f4260 100644
--- a/mysql-test/r/symlink.result
+++ b/mysql-test/r/symlink.result
@@ -91,23 +91,15 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
CREATE TABLE t1(a INT)
-DATA DIRECTORY='TEST_DIR/master-data/mysql'
-INDEX DIRECTORY='TEST_DIR/master-data/mysql';
-RENAME TABLE t1 TO user;
-ERROR HY000: Can't create/write to file 'TEST_DIR/master-data/mysql/user.MYI' (Errcode: 17)
-DROP TABLE t1;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `i` int(11) default NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-drop table t1;
-show create table t1;
-Table Create Table
-t1 CREATE TABLE `t1` (
- `i` int(11) default NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-drop table t1;
+DATA DIRECTORY='TEST_DIR/tmp'
+INDEX DIRECTORY='TEST_DIR/tmp';
+ERROR HY000: Can't create/write to file 'TEST_DIR/tmp/t1.MYI' (Errcode: 17)
+CREATE TABLE t2(a INT)
+DATA DIRECTORY='TEST_DIR/tmp'
+INDEX DIRECTORY='TEST_DIR/tmp';
+RENAME TABLE t2 TO t1;
+ERROR HY000: Can't create/write to file 'TEST_DIR/tmp/t1.MYI' (Errcode: 17)
+DROP TABLE t2;
show create table t1;
Table Create Table
t1 CREATE TEMPORARY TABLE `t1` (
@@ -144,4 +136,16 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/'
drop table t1;
deallocate prepare stmt;
+CREATE TABLE t1(a INT)
+DATA DIRECTORY='TEST_DIR/var/master-data/test';
+ERROR HY000: Incorrect arguments to DATA DIRECORY
+CREATE TABLE t1(a INT)
+DATA DIRECTORY='/home/gluh/MySQL/Merge/4.1-opt/mysql-test/var/master-data/';
+ERROR HY000: Incorrect arguments to DATA DIRECORY
+CREATE TABLE t1(a INT)
+INDEX DIRECTORY='/home/gluh/MySQL/Merge/4.1-opt/mysql-test/var/master-data';
+ERROR HY000: Incorrect arguments to INDEX DIRECORY
+CREATE TABLE t1(a INT)
+INDEX DIRECTORY='/home/gluh/MySQL/Merge/4.1-opt/mysql-test/var/master-data_var';
+ERROR HY000: Can't create/write to file '/home/gluh/MySQL/Merge/4.1-opt/mysql-test/var/master-data_var/t1.MYI' (Errcode: 2)
End of 4.1 tests
diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test
index 40127a697ac..7dfccaad8dc 100644
--- a/mysql-test/t/symlink.test
+++ b/mysql-test/t/symlink.test
@@ -121,29 +121,22 @@ drop table t1;
#
# BUG#32111 - Security Breach via DATA/INDEX DIRECORY and RENAME TABLE
#
+--write_file $MYSQLTEST_VARDIR/tmp/t1.MYI
+EOF
--replace_result $MYSQLTEST_VARDIR TEST_DIR
+--error 1
eval CREATE TABLE t1(a INT)
-DATA DIRECTORY='$MYSQLTEST_VARDIR/master-data/mysql'
-INDEX DIRECTORY='$MYSQLTEST_VARDIR/master-data/mysql';
+DATA DIRECTORY='$MYSQLTEST_VARDIR/tmp'
+INDEX DIRECTORY='$MYSQLTEST_VARDIR/tmp';
+--replace_result $MYSQLTEST_VARDIR TEST_DIR
+eval CREATE TABLE t2(a INT)
+DATA DIRECTORY='$MYSQLTEST_VARDIR/tmp'
+INDEX DIRECTORY='$MYSQLTEST_VARDIR/tmp';
--replace_result $MYSQLTEST_VARDIR 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)
-#
-disable_query_log;
-eval create table t1 (i int) data directory = "$MYSQL_TEST_DIR/var/master-data/test/";
-enable_query_log;
-show create table t1;
-drop table t1;
-disable_query_log;
-eval create table t1 (i int) index directory = "$MYSQL_TEST_DIR/var/master-data/test/";
-enable_query_log;
-show create table t1;
-drop table t1;
+RENAME TABLE t2 TO t1;
+DROP TABLE t2;
+--remove_file $MYSQLTEST_VARDIR/tmp/t1.MYI
#
# Bug#8706 - temporary table with data directory option fails
@@ -201,4 +194,21 @@ show create table t1;
drop table t1;
deallocate prepare stmt;
+#
+# Bug#32167 another privilege bypass with DATA/INDEX DIRECORY
+#
+--replace_result $MYSQL_TEST_DIR TEST_DIR
+--error 1210
+eval CREATE TABLE t1(a INT)
+DATA DIRECTORY='$MYSQL_TEST_DIR/var/master-data/test';
+--error 1210
+eval CREATE TABLE t1(a INT)
+DATA DIRECTORY='$MYSQL_TEST_DIR/var/master-data/';
+--error 1210
+eval CREATE TABLE t1(a INT)
+INDEX DIRECTORY='$MYSQL_TEST_DIR/var/master-data';
+--error 1
+eval CREATE TABLE t1(a INT)
+INDEX DIRECTORY='$MYSQL_TEST_DIR/var/master-data_var';
+
--echo End of 4.1 tests
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index b6170ba35f9..4b0031d1f2a 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -890,6 +890,7 @@ void my_dbopt_free(void);
extern time_t start_time;
extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH],
mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[],
+ mysql_unpacked_real_data_home[],
def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
#define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list))
extern MY_TMPDIR mysql_tmpdir_list;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 62105e0093a..8111df7ad4d 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -390,6 +390,7 @@ const char *opt_date_time_formats[3];
char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
char *language_ptr, *default_collation_name, *default_character_set_name;
char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home;
+char mysql_unpacked_real_data_home[FN_REFLEN];
struct passwd *user_info;
char server_version[SERVER_VERSION_LENGTH];
char *mysqld_unix_port, *opt_mysql_tmpdir;
@@ -6896,6 +6897,9 @@ static void fix_paths(void)
pos[1]= 0;
}
convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
+ (void) fn_format(buff, mysql_real_data_home, "", "",
+ (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS));
+ (void) unpack_dirname(mysql_unpacked_real_data_home, buff);
convert_dirname(language,language,NullS);
(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);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 24f9ef30569..4bbd425d80b 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -65,7 +65,8 @@ static bool append_file_to_dir(THD *thd, const char **filename_ptr,
const char *table_name);
static TABLE_LIST* get_table_by_alias(TABLE_LIST* tl, const char* db,
- const char* alias);
+ const char* alias);
+static bool test_if_data_home_dir(const char *dir);
const char *any_db="*any*"; // Special symbol for check_access
@@ -2531,6 +2532,20 @@ mysql_execute_command(THD *thd)
"INDEX DIRECTORY option ignored");
create_info.data_file_name= create_info.index_file_name= NULL;
#else
+
+ if (test_if_data_home_dir(lex->create_info.data_file_name))
+ {
+ my_error(ER_WRONG_ARGUMENTS,MYF(0),"DATA DIRECORY");
+ res= -1;
+ break;
+ }
+ if (test_if_data_home_dir(lex->create_info.index_file_name))
+ {
+ my_error(ER_WRONG_ARGUMENTS,MYF(0),"INDEX DIRECORY");
+ res= -1;
+ break;
+ }
+
/* Fix names if symlinked tables */
if (append_file_to_dir(thd, &create_info.data_file_name,
create_table->real_name) ||
@@ -5920,3 +5935,47 @@ Item *negate_expression(THD *thd, Item *expr)
return negated;
return new Item_func_not(expr);
}
+
+
+/*
+ Check if path does not contain mysql data home directory
+
+ SYNOPSIS
+ test_if_data_home_dir()
+ dir directory
+ conv_home_dir converted data home directory
+ home_dir_len converted data home directory length
+
+ RETURN VALUES
+ 0 ok
+ 1 error
+*/
+
+static bool test_if_data_home_dir(const char *dir)
+{
+ char path[FN_REFLEN], conv_path[FN_REFLEN];
+ uint dir_len, home_dir_len= strlen(mysql_unpacked_real_data_home);
+ DBUG_ENTER("test_if_data_home_dir");
+
+ if (!dir)
+ DBUG_RETURN(0);
+
+ (void) fn_format(path, dir, "", "",
+ (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS));
+ dir_len= unpack_dirname(conv_path, dir);
+
+ if (home_dir_len <= dir_len)
+ {
+ if (lower_case_file_system)
+ {
+ if (!my_strnncoll(default_charset_info, (const uchar*) conv_path,
+ home_dir_len,
+ (const uchar*) mysql_unpacked_real_data_home,
+ home_dir_len))
+ DBUG_RETURN(1);
+ }
+ else if (!memcmp(conv_path, mysql_unpacked_real_data_home, home_dir_len))
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}