[Pkg-mysql-commits] r1346 - in trunk/debian: . patches

Norbert Tretkowski nobse at alioth.debian.org
Thu Dec 4 20:14:56 UTC 2008


Author: nobse
Date: 2008-12-04 20:14:56 +0000 (Thu, 04 Dec 2008)
New Revision: 1346

Added:
   trunk/debian/patches/92_SECURITY_CVE-2008-4098.dpatch
Removed:
   trunk/debian/patches/92_SECURITY_CVE-2008-2079.dpatch
Modified:
   trunk/debian/changelog
   trunk/debian/patches/00list
Log:
Merge 5.0.51a-18

Modified: trunk/debian/changelog
===================================================================
--- trunk/debian/changelog	2008-11-27 08:48:15 UTC (rev 1345)
+++ trunk/debian/changelog	2008-12-04 20:14:56 UTC (rev 1346)
@@ -1,3 +1,13 @@
+mysql-dfsg-5.0 (5.0.51a-18) testing-proposed-updates; urgency=high
+
+  * SECURITY:
+    Fix for CVE-2008-4098: Inadequate validation of paths used in DATA
+    DIRECTORY and INDEX DIRECTORY clauses of CREATE TABLE statements enabled
+    attackers to write to tables in other databases to which they could not
+    ordinarily have access.
+
+ -- Devin Carraway <devin at debian.org>  Tue, 25 Nov 2008 05:38:45 +0000
+
 mysql-dfsg-5.0 (5.0.51a-17) testing-proposed-updates; urgency=low
 
   * Don't use commented out passwords from debian.cnf. (closes: #453820)

Modified: trunk/debian/patches/00list
===================================================================
--- trunk/debian/patches/00list	2008-11-27 08:48:15 UTC (rev 1345)
+++ trunk/debian/patches/00list	2008-12-04 20:14:56 UTC (rev 1346)
@@ -22,5 +22,5 @@
 89_ndb__staticlib.dpatch
 90_upstreamdebiandir.dpatch
 91_SECURITY_CVE-2007-5925.dpatch
-92_SECURITY_CVE-2008-2079.dpatch
+92_SECURITY_CVE-2008-4098.dpatch
 93_SECURITY_CVE-2008-3963.dpatch

Deleted: trunk/debian/patches/92_SECURITY_CVE-2008-2079.dpatch
===================================================================
--- trunk/debian/patches/92_SECURITY_CVE-2008-2079.dpatch	2008-11-27 08:48:15 UTC (rev 1345)
+++ trunk/debian/patches/92_SECURITY_CVE-2008-2079.dpatch	2008-12-04 20:14:56 UTC (rev 1346)
@@ -1,380 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## 92_SECURITY_CVE-2008-2079.dpatch by Norbert Tretkowski <nobse at debian.org>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Fix for CVE-2008-2079: It was possible to circumvent privileges through
-## DP: the creation of MyISAM tables employing the DATA DIRECTORY and INDEX
-## DP: DIRECTORY options to overwrite existing table files in the MySQL data
-## DP: directory. Use of the MySQL data directory in DATA DIRECTORY and INDEX
-## DP: DIRECTORY is now disallowed.
-
- at DPATCH@
---- a/mysql-test/r/symlink.result.orig
-+++ b/mysql-test/r/symlink.result
-@@ -100,23 +100,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` (
-@@ -138,27 +130,38 @@ select * from t1;
- a
- 42
- drop table t1;
-+execute stmt;
-+show create table t1;
-+Table	Create Table
-+t1	CREATE TABLE `t1` (
-+  `c` char(10) default NULL
-+) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/'
-+drop table t1;
-+execute stmt;
-+show create table t1;
-+Table	Create Table
-+t1	CREATE TABLE `t1` (
-+  `c` char(10) default NULL
-+) 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';
-+Got one of the listed errors
-+CREATE TABLE t1(a INT)
-+DATA DIRECTORY='TEST_DIR/var/master-data/';
-+Got one of the listed errors
-+CREATE TABLE t1(a INT)
-+INDEX DIRECTORY='TEST_DIR/var/master-data';
-+Got one of the listed errors
-+CREATE TABLE t1(a INT)
-+INDEX DIRECTORY='TEST_DIR/var/master-data_var';
-+Got one of the listed errors
- End of 4.1 tests
--CREATE DATABASE db1;
--CREATE DATABASE db2;
--USE db2;
--INSERT INTO db2.t1 VALUES (1);
--SELECT * FROM db2.t1;
--b
--1
--RESET QUERY CACHE;
--USE db1;
- SET SESSION keep_files_on_create = TRUE;
- CREATE TABLE t1 (a INT) ENGINE MYISAM;
--ERROR HY000: Can't create/write to file './db1/t1.MYD' (Errcode: 17)
--CREATE TABLE t3 (a INT) Engine=MyISAM;
--INSERT INTO t3 VALUES (1),(2),(3);
--TRUNCATE TABLE t3;
--SELECT * from t3;
--a
--SET SESSION keep_files_on_create = DEFAULT;
--DROP TABLE db2.t1, db1.t3;
--DROP DATABASE db1;
--DROP DATABASE db2;
--USE test;
-+ERROR HY000: Can't create/write to file './test/t1.MYD' (Errcode: 17)
-+SET SESSION keep_files_on_create = FALSE;
-+CREATE TABLE t1 (a INT) ENGINE MYISAM;
-+DROP TABLE t1;
- End of 5.0 tests
---- a/sql/mysql_priv.h.orig
-+++ b/sql/mysql_priv.h
-@@ -1255,6 +1255,7 @@ void my_dbopt_free(void);
- extern time_t server_start_time, flush_status_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;
---- a/sql/mysqld.cc.orig
-+++ b/sql/mysqld.cc
-@@ -453,14 +453,13 @@ char log_error_file[FN_REFLEN], glob_hos
- char mysql_real_data_home[FN_REFLEN],
-      language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
-      *opt_init_file, *opt_tc_log_file,
-+     mysql_unpacked_real_data_home[FN_REFLEN],
-      def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
--
-+char *mysql_data_home= mysql_real_data_home;
- const key_map key_map_empty(0);
- key_map key_map_full(0);                        // Will be initialized later
- 
- const char *opt_date_time_formats[3];
--
--char *mysql_data_home= mysql_real_data_home;
- char server_version[SERVER_VERSION_LENGTH];
- char *mysqld_unix_port, *opt_mysql_tmpdir;
- const char **errmesg;			/* Error messages */
-@@ -7565,6 +7564,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);
---- ../old/mysql-dfsg-5.0-5.0.51a/sql/sql_parse.cc	2008-01-11 14:43:38.000000000 +0000
-+++ mysql-dfsg-5.0-5.0.51a/sql/sql_parse.cc	2008-07-12 06:18:51.000000000 +0000
-@@ -76,6 +76,7 @@
- static bool append_file_to_dir(THD *thd, const char **filename_ptr,
- 			       const char *table_name);
- static bool check_show_create_table_access(THD *thd, TABLE_LIST *table);
-+static bool test_if_data_home_dir(const char *dir);
- 
- const char *any_db="*any*";	// Special symbol for check_access
- 
-@@ -3001,6 +3002,20 @@
-                    "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->table_name) ||
-@@ -7843,3 +7858,49 @@
- 
-   return TRUE;
- }
-+
-+
-+/*
-+  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[PATH_MAX+1], real_path[PATH_MAX+1];
-+  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));
-+  if (!realpath(path, real_path))
-+    DBUG_RETURN(1);
-+  dir_len= unpack_dirname(conv_path, real_path);
-+
-+  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);
-+}
---- ../old/mysql-dfsg-5.0-5.0.51a/mysql-test/t/symlink.test	2008-01-11 15:23:24.000000000 +0000
-+++ mysql-dfsg-5.0-5.0.51a/mysql-test/t/symlink.test	2008-07-13 14:13:04.000000000 +0000
-@@ -71,17 +71,17 @@
- SHOW CREATE TABLE t9;
- 
- disable_query_log;
----error 1103,1103
-+--error 1210,1210
- create table t1 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="tmp";
- 
- # Check that we cannot link over a table from another database.
- 
- create database mysqltest;
- 
----error 1,1
-+--error 1210,1210
- create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="/this-dir-does-not-exist";
- 
----error 1103,1103
-+--error 1210,1210
- create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="not-hard-path";
- 
- # Should fail becasue the file t9.MYI already exist in 'run'
-@@ -127,29 +127,22 @@
- #
- # 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 = "$MYSQLTEST_VARDIR/master-data/test/";
--enable_query_log;
--show create table t1;
--drop table t1;
--disable_query_log;
--eval create table t1 (i int) index directory = "$MYSQLTEST_VARDIR/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
-@@ -188,44 +181,61 @@
- select * from t1;
- drop table t1;
- 
----echo End of 4.1 tests
--
- #
--# Bug #29325: create table overwrites .MYD file of other table (datadir)
-+# CREATE TABLE with DATA DIRECTORY option
- #
--
--CREATE DATABASE db1; 
--CREATE DATABASE db2;
--
--USE db2;
-+# Protect ourselves from data left in tmp/ by a previos possibly failed
-+# test
-+--system rm -f $MYSQLTEST_VARDIR/tmp/t1.*
- --disable_query_log
--eval CREATE TABLE t1 (b INT) ENGINE MYISAM
--DATA DIRECTORY = '$MYSQLTEST_VARDIR/master-data/db1/';
-+eval prepare stmt from "create table t1 (c char(10)) data directory='$MYSQLTEST_VARDIR/tmp'";
- --enable_query_log
-+execute stmt;
-+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-+show create table t1;
-+drop table t1;
-+execute stmt;
-+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
-+show create table t1;
-+drop table t1;
-+deallocate prepare stmt;
- 
--INSERT INTO db2.t1 VALUES (1);
--SELECT * FROM db2.t1;
--RESET QUERY CACHE;
-+#
-+# Bug#32167 another privilege bypass with DATA/INDEX DIRECORY
-+#
-+--replace_result $MYSQL_TEST_DIR TEST_DIR
-+--error 1,1210
-+eval CREATE TABLE t1(a INT)
-+DATA DIRECTORY='$MYSQL_TEST_DIR/var/master-data/test';
-+--replace_result $MYSQL_TEST_DIR TEST_DIR
-+--error 1,1210
-+eval CREATE TABLE t1(a INT)
-+DATA DIRECTORY='$MYSQL_TEST_DIR/var/master-data/';
-+--replace_result $MYSQL_TEST_DIR TEST_DIR
-+--error 1,1210
-+eval CREATE TABLE t1(a INT)
-+INDEX DIRECTORY='$MYSQL_TEST_DIR/var/master-data';
-+--replace_result $MYSQL_TEST_DIR TEST_DIR
-+--error 1,1210
-+eval CREATE TABLE t1(a INT)
-+INDEX DIRECTORY='$MYSQL_TEST_DIR/var/master-data_var';
- 
--USE db1;
-+--echo End of 4.1 tests
- 
--#no warning from create table
-+#
-+# Bug #29325: create table overwrites .MYD file of other table (datadir)
-+#
- SET SESSION keep_files_on_create = TRUE;
-+--write_file $MYSQLTEST_VARDIR/master-data/test/t1.MYD
-+EOF
- --disable_abort_on_error
-+--error 1
- CREATE TABLE t1 (a INT) ENGINE MYISAM;
-+--error 0,1
-+--remove_file $MYSQLTEST_VARDIR/master-data/test/t1.MYD;
- --enable_abort_on_error
--
--CREATE TABLE t3 (a INT) Engine=MyISAM;
--INSERT INTO t3 VALUES (1),(2),(3);
--TRUNCATE TABLE t3;
--SELECT * from t3;
--
--SET SESSION keep_files_on_create = DEFAULT;
--
--DROP TABLE db2.t1, db1.t3;
--DROP DATABASE db1;
--DROP DATABASE db2;
--USE test;
--
-+SET SESSION keep_files_on_create = FALSE;
-+CREATE TABLE t1 (a INT) ENGINE MYISAM;
-+DROP TABLE t1;
- 
- --echo End of 5.0 tests

Added: trunk/debian/patches/92_SECURITY_CVE-2008-4098.dpatch
===================================================================
--- trunk/debian/patches/92_SECURITY_CVE-2008-4098.dpatch	                        (rev 0)
+++ trunk/debian/patches/92_SECURITY_CVE-2008-4098.dpatch	2008-12-04 20:14:56 UTC (rev 1346)
@@ -0,0 +1,634 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 92_SECURITY_CVE-2008-4098.dpatch by Devin Carraway <devin at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Backport of upstream fix to CVE-2008-4098, superceding fix to
+## CVE-2008-2079.  Limitations in validation of user-supplied DATA DIRECTORY
+## and INDEX DIRECTORY clauses to CREATE TABLE statements allowed hostile
+## users with write access to the db server's filesystem to acquire write
+## privileges to other databases.  This patch was prepared for 5.0.32, but
+## applies to 5.0.51a without issues.
+
+ at DPATCH@
+diff -aruN mysql-dfsg-5.0-5.0.32.orig/include/my_sys.h mysql-dfsg-5.0-5.0.32/include/my_sys.h
+--- mysql-dfsg-5.0-5.0.32.orig/include/my_sys.h	2006-12-20 03:14:47.000000000 -0800
++++ mysql-dfsg-5.0-5.0.32/include/my_sys.h	2008-10-26 22:58:47.000000000 -0700
+@@ -570,6 +570,7 @@
+ extern File my_dup(File file, myf MyFlags);
+ extern int my_mkdir(const char *dir, int Flags, myf MyFlags);
+ extern int my_readlink(char *to, const char *filename, myf MyFlags);
++extern int my_is_symlink(const char *filename);
+ extern int my_realpath(char *to, const char *filename, myf MyFlags);
+ extern File my_create_with_symlink(const char *linkname, const char *filename,
+ 				   int createflags, int access_flags,
+diff -aruN mysql-dfsg-5.0-5.0.32.orig/include/myisam.h mysql-dfsg-5.0-5.0.32/include/myisam.h
+--- mysql-dfsg-5.0-5.0.32.orig/include/myisam.h	2006-12-20 03:14:04.000000000 -0800
++++ mysql-dfsg-5.0-5.0.32/include/myisam.h	2008-10-26 22:59:31.000000000 -0700
+@@ -268,6 +268,10 @@
+ extern my_off_t myisam_max_temp_length;
+ extern ulong myisam_bulk_insert_tree_size, myisam_data_pointer_size;
+ 
++/* usually used to check if a symlink points into the mysql data home */
++/* which is normally forbidden                                        */
++extern int (*myisam_test_invalid_symlink)(const char *filename);
++
+ 	/* Prototypes for myisam-functions */
+ 
+ extern int mi_close(struct st_myisam_info *file);
+diff -aruN mysql-dfsg-5.0-5.0.32.orig/myisam/mi_check.c mysql-dfsg-5.0-5.0.32/myisam/mi_check.c
+--- mysql-dfsg-5.0-5.0.32.orig/myisam/mi_check.c	2006-12-20 03:14:48.000000000 -0800
++++ mysql-dfsg-5.0-5.0.32/myisam/mi_check.c	2008-10-26 23:00:39.000000000 -0700
+@@ -1560,7 +1560,7 @@
+ 			    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;
+     }
+   }
+@@ -2340,7 +2340,7 @@
+ 			    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;
+     }
+   }
+@@ -2872,7 +2872,7 @@
+ 			    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 -aruN mysql-dfsg-5.0-5.0.32.orig/myisam/mi_open.c mysql-dfsg-5.0-5.0.32/myisam/mi_open.c
+--- mysql-dfsg-5.0-5.0.32.orig/myisam/mi_open.c	2006-12-20 03:14:25.000000000 -0800
++++ mysql-dfsg-5.0-5.0.32/myisam/mi_open.c	2008-10-26 23:03:52.000000000 -0700
+@@ -75,7 +75,7 @@
+ 
+ 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],
+@@ -96,6 +96,15 @@
+   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)))
+   {
+@@ -448,7 +457,7 @@
+       lock_error=1;			/* Database unlocked */
+     }
+ 
+-    if (mi_open_datafile(&info, share, -1))
++    if (mi_open_datafile(&info, share, name, -1))
+       goto err;
+     errpos=5;
+ 
+@@ -518,7 +527,7 @@
+       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;
+@@ -1163,12 +1172,29 @@
+ 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,
+@@ -1177,7 +1203,7 @@
+   }
+   else
+ #endif
+-    info->dfile=my_open(share->data_file_name, share->mode | O_SHARE,
++    info->dfile=my_open(data_name, share->mode | O_SHARE,
+ 			MYF(MY_WME));
+   return info->dfile >= 0 ? 0 : 1;
+ }
+diff -aruN mysql-dfsg-5.0-5.0.32.orig/myisam/mi_static.c mysql-dfsg-5.0-5.0.32/myisam/mi_static.c
+--- mysql-dfsg-5.0-5.0.32.orig/myisam/mi_static.c	2006-12-20 03:14:00.000000000 -0800
++++ mysql-dfsg-5.0-5.0.32/myisam/mi_static.c	2008-10-26 23:04:25.000000000 -0700
+@@ -42,6 +42,15 @@
+ 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 -aruN mysql-dfsg-5.0-5.0.32.orig/myisam/myisamchk.c mysql-dfsg-5.0-5.0.32/myisam/myisamchk.c
+--- mysql-dfsg-5.0-5.0.32.orig/myisam/myisamchk.c	2006-12-20 03:14:39.000000000 -0800
++++ mysql-dfsg-5.0-5.0.32/myisam/myisamchk.c	2008-10-26 23:04:43.000000000 -0700
+@@ -1039,7 +1039,7 @@
+ 	  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 -aruN mysql-dfsg-5.0-5.0.32.orig/myisam/myisamdef.h mysql-dfsg-5.0-5.0.32/myisam/myisamdef.h
+--- mysql-dfsg-5.0-5.0.32.orig/myisam/myisamdef.h	2006-12-20 03:14:10.000000000 -0800
++++ mysql-dfsg-5.0-5.0.32/myisam/myisamdef.h	2008-10-26 23:05:17.000000000 -0700
+@@ -738,7 +738,9 @@
+ 
+ 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);
+ 
+diff -aruN mysql-dfsg-5.0-5.0.32.orig/mysys/my_symlink.c mysql-dfsg-5.0-5.0.32/mysys/my_symlink.c
+--- mysql-dfsg-5.0-5.0.32.orig/mysys/my_symlink.c	2006-12-20 03:14:04.000000000 -0800
++++ mysql-dfsg-5.0-5.0.32/mysys/my_symlink.c	2008-10-26 23:10:44.000000000 -0700
+@@ -107,38 +107,38 @@
+ #define BUFF_LEN FN_LEN
+ #endif
+ 
++int my_is_symlink(const char *filename __attribute__((unused)))
++{
++  struct stat stat_buff;
++  return !lstat(filename, &stat_buff) && S_ISLNK(stat_buff.st_mode);
++}
++
++
+ int my_realpath(char *to, const char *filename,
+ 		myf MyFlags __attribute__((unused)))
+ {
+ #if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH)
+   int result=0;
+   char buff[BUFF_LEN];
+-  struct stat stat_buff;
++  char *ptr;
+   DBUG_ENTER("my_realpath");
+ 
+-  if (!(MyFlags & MY_RESOLVE_LINK) ||
+-      (!lstat(filename,&stat_buff) && S_ISLNK(stat_buff.st_mode)))
+-  {
+-    char *ptr;
+-    DBUG_PRINT("info",("executing realpath"));
+-    if ((ptr=realpath(filename,buff)))
+-    {
++  DBUG_PRINT("info",("executing realpath"));
++  if ((ptr=realpath(filename,buff)))
+       strmake(to,ptr,FN_REFLEN-1);
+-    }
+-    else
+-    {
+-      /*
+-	Realpath didn't work;  Use my_load_path() which is a poor substitute
+-	original name but will at least be able to resolve paths that starts
+-	with '.'.
+-      */
+-      DBUG_PRINT("error",("realpath failed with errno: %d", errno));
+-      my_errno=errno;
+-      if (MyFlags & MY_WME)
+-	my_error(EE_REALPATH, MYF(0), filename, my_errno);
+-      my_load_path(to, filename, NullS);
+-      result= -1;
+-    }
++  else
++  {
++    /*
++      Realpath didn't work;  Use my_load_path() which is a poor substitute
++      original name but will at least be able to resolve paths that starts
++      with '.'.
++    */
++    DBUG_PRINT("error",("realpath failed with errno: %d", errno));
++    my_errno=errno;
++    if (MyFlags & MY_WME)
++      my_error(EE_REALPATH, MYF(0), filename, my_errno);
++    my_load_path(to, filename, NullS);
++    result= -1;
+   }
+   DBUG_RETURN(result);
+ #else
+diff -aruN mysql-dfsg-5.0-5.0.32.orig/sql/mysql_priv.h mysql-dfsg-5.0-5.0.32/sql/mysql_priv.h
+--- mysql-dfsg-5.0-5.0.32.orig/sql/mysql_priv.h	2008-10-26 22:55:09.000000000 -0700
++++ mysql-dfsg-5.0-5.0.32/sql/mysql_priv.h	2008-10-26 23:38:05.000000000 -0700
+@@ -1193,7 +1193,9 @@
+ 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)];
++extern int mysql_unpacked_real_data_home_len;
+ #define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list))
+ extern MY_TMPDIR mysql_tmpdir_list;
+ extern const char *command_name[];
+@@ -1684,4 +1686,6 @@
+ #define check_stack_overrun(A, B, C) 0
+ #endif
+ 
++extern "C" int test_if_data_home_dir(const char *dir);
++
+ #endif /* MYSQL_CLIENT */
+diff -aruN mysql-dfsg-5.0-5.0.32.orig/sql/mysqld.cc mysql-dfsg-5.0-5.0.32/sql/mysqld.cc
+--- mysql-dfsg-5.0-5.0.32.orig/sql/mysqld.cc	2006-12-20 03:14:10.000000000 -0800
++++ mysql-dfsg-5.0-5.0.32/sql/mysqld.cc	2008-10-26 23:25:18.000000000 -0700
+@@ -437,8 +437,9 @@
+ char mysql_real_data_home[FN_REFLEN],
+      language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN],
+      *opt_init_file, *opt_tc_log_file,
++     mysql_unpacked_real_data_home[FN_REFLEN],
+      def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
+-
++int mysql_unpacked_real_data_home_len;
+ const key_map key_map_empty(0);
+ key_map key_map_full(0);                        // Will be initialized later
+ 
+@@ -6344,6 +6345,7 @@
+   /* Things reset to zero */
+   opt_skip_slave_start= opt_reckless_slave = 0;
+   mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
++  myisam_test_invalid_symlink= test_if_data_home_dir;
+   opt_log= opt_update_log= opt_slow_log= 0;
+   opt_bin_log= 0;
+   opt_disable_networking= opt_skip_show_db=0;
+@@ -7358,7 +7360,11 @@
+   convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
+   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);
++  my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0));
++  mysql_unpacked_real_data_home_len= strlen(mysql_unpacked_real_data_home);
++  if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len-1] == FN_LIBCHAR)
++    --mysql_unpacked_real_data_home_len;
++
+   (void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home);
+ 
+   char *sharedir=get_relative_path(SHAREDIR);
+diff -aruN mysql-dfsg-5.0-5.0.32.orig/sql/sql_parse.cc mysql-dfsg-5.0-5.0.32/sql/sql_parse.cc
+--- mysql-dfsg-5.0-5.0.32.orig/sql/sql_parse.cc	2008-10-26 22:55:09.000000000 -0700
++++ mysql-dfsg-5.0-5.0.32/sql/sql_parse.cc	2008-10-26 23:23:01.000000000 -0700
+@@ -2890,6 +2890,19 @@
+ #ifndef HAVE_READLINK
+     lex->create_info.data_file_name=lex->create_info.index_file_name=0;
+ #else
++    if (test_if_data_home_dir(lex->create_info.data_file_name))
++    {
++      my_error(ER_WRONG_ARGUMENTS,MYF(0),"DATA DIRECTORY");
++      res= -1;
++      break;
++    }
++    if (test_if_data_home_dir(lex->create_info.index_file_name))
++    {
++      my_error(ER_WRONG_ARGUMENTS,MYF(0),"INDEX DIRECTORY");
++      res= -1;
++      break;
++    }
++
+     /* Fix names if symlinked tables */
+     if (append_file_to_dir(thd, &lex->create_info.data_file_name,
+ 			   create_table->table_name) ||
+@@ -7664,3 +7677,55 @@
+ 
+   return TRUE;
+ }
++
++
++/*
++  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  
++*/
++
++C_MODE_START
++
++int test_if_data_home_dir(const char *dir)
++{
++  char path[FN_REFLEN];
++  int dir_len;
++  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= strlen(path);
++  if (mysql_unpacked_real_data_home_len<= dir_len)
++  {
++    if (dir_len > mysql_unpacked_real_data_home_len &&
++        path[mysql_unpacked_real_data_home_len] != FN_LIBCHAR)
++      DBUG_RETURN(0);
++
++    if (lower_case_file_system)
++    {
++      if (!my_strnncoll(default_charset_info, (const uchar*) path,
++                        mysql_unpacked_real_data_home_len,
++                        (const uchar*) mysql_unpacked_real_data_home,
++                        mysql_unpacked_real_data_home_len))
++        DBUG_RETURN(1);
++    }
++    else if (!memcmp(path, mysql_unpacked_real_data_home,
++                     mysql_unpacked_real_data_home_len))
++      DBUG_RETURN(1);
++  }
++  DBUG_RETURN(0);
++}
++
++C_MODE_END
+
+diff -aruN mysql-dfsg-5.0-5.0.51a/mysql-test/t/symlink.test mysql-dfsg-5.0-5.0.51a.tmp/mysql-test/t/symlink.test
+--- mysql-dfsg-5.0-5.0.51a/mysql-test/t/symlink.test	2008-01-11 15:23:24.000000000 +0000
++++ mysql-dfsg-5.0-5.0.51a.tmp/mysql-test/t/symlink.test	1970-01-01 00:00:00.000000000 +0000
+@@ -1,231 +0,0 @@
+--- require r/have_symlink.require
+-disable_query_log;
+-show variables like "have_symlink";
+-enable_query_log;
+-
+---source include/not_windows.inc
+-
+---disable_warnings
+-drop table if exists t1,t2,t7,t8,t9;
+-drop database if exists mysqltest;
+---enable_warnings
+-
+-#
+-# First create little data to play with
+-#
+-
+-create table t1 (a int not null auto_increment, b char(16) not null, primary key (a));
+-create table t2 (a int not null auto_increment, b char(16) not null, primary key (a));
+-insert into t1 (b) values ("test"),("test1"),("test2"),("test3");
+-insert into t2 (b) select b from t1;
+-insert into t1 (b) select b from t2;
+-insert into t2 (b) select b from t1;
+-insert into t1 (b) select b from t2;
+-insert into t2 (b) select b from t1;
+-insert into t1 (b) select b from t2;
+-insert into t2 (b) select b from t1;
+-insert into t1 (b) select b from t2;
+-insert into t2 (b) select b from t1;
+-insert into t1 (b) select b from t2;
+-insert into t2 (b) select b from t1;
+-insert into t1 (b) select b from t2;
+-insert into t2 (b) select b from t1;
+-insert into t1 (b) select b from t2;
+-insert into t2 (b) select b from t1;
+-insert into t1 (b) select b from t2;
+-insert into t2 (b) select b from t1;
+-insert into t1 (b) select b from t2;
+-drop table t2;
+-
+-#
+-# Start the test
+-# We use t9 here to not crash with tables generated by the backup test
+-# 
+-
+-disable_query_log;
+-eval create table t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="$MYSQLTEST_VARDIR/tmp" index directory="$MYSQLTEST_VARDIR/run";
+-enable_query_log;
+-
+-insert into t9 select * from t1;
+-check table t9;
+-optimize table t9;
+-repair table t9;
+-alter table t9 add column c int not null;
+-
+---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-show create table t9;
+-
+-# Test renames
+-alter table t9 rename t8, add column d int not null;
+-alter table t8 rename t7;
+-rename table t7 to t9;
+-# Drop old t1 table, keep t9
+-drop table t1;
+-
+-#
+-# Test error handling
+-# Note that we are using the above table t9 here!
+-#
+-
+---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-SHOW CREATE TABLE t9;
+-
+-disable_query_log;
+---error 1103,1103
+-create table t1 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="tmp";
+-
+-# Check that we cannot link over a table from another database.
+-
+-create database mysqltest;
+-
+---error 1,1
+-create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="/this-dir-does-not-exist";
+-
+---error 1103,1103
+-create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="not-hard-path";
+-
+-# Should fail becasue the file t9.MYI already exist in 'run'
+---error 1,1,1105
+-eval create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="$MYSQLTEST_VARDIR/run";
+-
+-# Should fail becasue the file t9.MYD already exist in 'tmp'
+---error 1,1
+-eval create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="$MYSQLTEST_VARDIR/tmp";
+-enable_query_log;
+-
+-# Check moving table t9 from default database to mysqltest;
+-# In this case the symlinks should be removed.
+-
+-alter table t9 rename mysqltest.t9;
+-select count(*) from mysqltest.t9;
+---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-show create table mysqltest.t9;
+-drop database mysqltest;
+-
+-#
+-# Test changing data dir (Bug #1662)
+-#
+-
+-create table t1 (a int not null) engine=myisam;
+-disable_query_log;
+-eval alter table t1 data directory="$MYSQLTEST_VARDIR/tmp";
+-enable_query_log;
+---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-show create table t1;
+-alter table t1 add b int;
+-disable_query_log;
+-eval alter table t1 data directory="$MYSQLTEST_VARDIR/log";
+-enable_query_log;
+---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-show create table t1;
+-disable_query_log;
+-eval alter table t1 index directory="$MYSQLTEST_VARDIR/log";
+-enable_query_log;
+-show create table t1;
+-drop table t1;
+-
+-#
+-# BUG#32111 - Security Breach via DATA/INDEX DIRECORY and RENAME TABLE
+-#
+---replace_result $MYSQLTEST_VARDIR TEST_DIR
+-eval CREATE TABLE t1(a INT)
+-DATA DIRECTORY='$MYSQLTEST_VARDIR/master-data/mysql'
+-INDEX DIRECTORY='$MYSQLTEST_VARDIR/master-data/mysql';
+---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 = "$MYSQLTEST_VARDIR/master-data/test/";
+-enable_query_log;
+-show create table t1;
+-drop table t1;
+-disable_query_log;
+-eval create table t1 (i int) index directory = "$MYSQLTEST_VARDIR/master-data/test/";
+-enable_query_log;
+-show create table t1;
+-drop table t1;
+-
+-#
+-# Bug#8706 - temporary table with data directory option fails
+-#
+-connect (session1,localhost,root,,);
+-connect (session2,localhost,root,,);
+-
+-connection session1;
+-disable_query_log;
+-eval create temporary table t1 (a int) engine=myisam data directory="$MYSQLTEST_VARDIR/log" select 9 a;
+-enable_query_log;
+-# If running test suite with a non standard tmp dir, the "show create table"
+-# will print "DATA_DIRECTORY=". Use replace_result to mask it out
+---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-show create table t1;
+-
+-connection session2;
+-disable_query_log;
+-eval create temporary table t1 (a int) engine=myisam data directory="$MYSQLTEST_VARDIR/log" select 99 a;
+-enable_query_log;
+-# If running test suite with a non standard tmp dir, the "show create table"
+-# will print "DATA_DIRECTORY=". Use replace_result to mask it out
+---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+-show create table t1;
+-
+-connection default;
+-create table t1 (a int) engine=myisam select 42 a;
+-
+-connection session1;
+-select * from t1;
+-disconnect session1;
+-connection session2;
+-select * from t1;
+-disconnect session2;
+-connection default;
+-select * from t1;
+-drop table t1;
+-
+---echo End of 4.1 tests
+-
+-#
+-# Bug #29325: create table overwrites .MYD file of other table (datadir)
+-#
+-
+-CREATE DATABASE db1; 
+-CREATE DATABASE db2;
+-
+-USE db2;
+---disable_query_log
+-eval CREATE TABLE t1 (b INT) ENGINE MYISAM
+-DATA DIRECTORY = '$MYSQLTEST_VARDIR/master-data/db1/';
+---enable_query_log
+-
+-INSERT INTO db2.t1 VALUES (1);
+-SELECT * FROM db2.t1;
+-RESET QUERY CACHE;
+-
+-USE db1;
+-
+-#no warning from create table
+-SET SESSION keep_files_on_create = TRUE;
+---disable_abort_on_error
+-CREATE TABLE t1 (a INT) ENGINE MYISAM;
+---enable_abort_on_error
+-
+-CREATE TABLE t3 (a INT) Engine=MyISAM;
+-INSERT INTO t3 VALUES (1),(2),(3);
+-TRUNCATE TABLE t3;
+-SELECT * from t3;
+-
+-SET SESSION keep_files_on_create = DEFAULT;
+-
+-DROP TABLE db2.t1, db1.t3;
+-DROP DATABASE db1;
+-DROP DATABASE db2;
+-USE test;
+-
+-
+---echo End of 5.0 tests




More information about the Pkg-mysql-commits mailing list