List:Commits« Previous MessageNext Message »
From:gluh Date:February 29 2008 9:55am
Subject:bk commit into 4.1 tree (gluh:1.2707) BUG#32167
View as plain text  
Below is the list of changes that have just been committed into a local
4.1 repository of gluh. When gluh does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-02-29 13:55:00+04:00, gluh@stripped +5 -0
  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@stripped, 2008-02-29 13:54:59+04:00, gluh@stripped +21 -17
    test result

  mysql-test/t/symlink.test@stripped, 2008-02-29 13:54:59+04:00, gluh@stripped +29 -19
    test case

  sql/mysql_priv.h@stripped, 2008-02-29 13:54:59+04:00, gluh@stripped +1 -0
    new variable mysql_unpacked_real_data_home

  sql/mysqld.cc@stripped, 2008-02-29 13:54:59+04:00, gluh@stripped +4 -0
    new variable mysql_unpacked_real_data_home

  sql/sql_parse.cc@stripped, 2008-02-29 13:54:59+04:00, gluh@stripped +60 -1
    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.

diff -Nrup a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result
--- a/mysql-test/r/symlink.result	2007-11-12 21:51:47 +04:00
+++ b/mysql-test/r/symlink.result	2008-02-29 13:54:59 +04:00
@@ -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 -Nrup a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test
--- a/mysql-test/t/symlink.test	2007-11-12 21:51:28 +04:00
+++ b/mysql-test/t/symlink.test	2008-02-29 13:54:59 +04:00
@@ -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
@@ -200,5 +193,22 @@ execute stmt;
 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 -Nrup a/sql/mysql_priv.h b/sql/mysql_priv.h
--- a/sql/mysql_priv.h	2007-11-09 16:05:01 +04:00
+++ b/sql/mysql_priv.h	2008-02-29 13:54:59 +04:00
@@ -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 -Nrup a/sql/mysqld.cc b/sql/mysqld.cc
--- a/sql/mysqld.cc	2007-11-29 14:52:36 +04:00
+++ b/sql/mysqld.cc	2008-02-29 13:54:59 +04:00
@@ -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 -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
--- a/sql/sql_parse.cc	2007-06-12 17:47:34 +05:00
+++ b/sql/sql_parse.cc	2008-02-29 13:54:59 +04:00
@@ -65,7 +65,8 @@ static bool append_file_to_dir(THD *thd,
 			       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) ||
@@ -5919,4 +5934,48 @@ Item *negate_expression(THD *thd, Item *
   if ((negated= expr->neg_transformer(thd)) != 0)
     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);
 }
Thread
bk commit into 4.1 tree (gluh:1.2707) BUG#32167gluh29 Feb