List:Commits« Previous MessageNext Message »
From:msvensson Date:February 14 2007 1:52pm
Subject:bk commit into 5.1 tree (msvensson:1.2435)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of msvensson. When msvensson 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, 2007-02-14 14:51:49+01:00, msvensson@stripped +15 -0
  Merge pilot.mysql.com:/home/msvensson/mysql/mysql-5.0-maint
  into  pilot.mysql.com:/home/msvensson/mysql/mysql-5.1-new-maint
  MERGE: 1.1810.2372.92

  mysql-test/mysql-test-run.pl@stripped, 2007-02-14 14:46:09+01:00, msvensson@stripped +0 -0
    Auto merged
    MERGE: 1.30.49.54

  mysql-test/r/loaddata.result@stripped, 2007-02-14 14:46:09+01:00, msvensson@stripped +0 -0
    Auto merged
    MERGE: 1.20.1.5

  mysql-test/r/query_cache.result@stripped, 2007-02-14 14:46:09+01:00, msvensson@stripped +0 -0
    Auto merged
    MERGE: 1.65.1.13

  mysql-test/r/type_blob.result@stripped, 2007-02-14 14:46:09+01:00, msvensson@stripped +0 -0
    Auto merged
    MERGE: 1.49.2.5

  mysql-test/t/loaddata.test@stripped, 2007-02-14 14:46:09+01:00, msvensson@stripped +0 -0
    Auto merged
    MERGE: 1.15.1.4

  mysql-test/t/query_cache.test@stripped, 2007-02-14 14:46:09+01:00, msvensson@stripped +0 -0
    Auto merged
    MERGE: 1.49.1.8

  mysql-test/t/type_blob.test@stripped, 2007-02-14 14:46:09+01:00, msvensson@stripped +0 -0
    Auto merged
    MERGE: 1.33.1.1

  sql/item_strfunc.cc@stripped, 2007-02-14 14:46:09+01:00, msvensson@stripped +0 -0
    Auto merged
    MERGE: 1.261.20.2

  sql/mysql_priv.h@stripped, 2007-02-14 14:46:09+01:00, msvensson@stripped +0 -0
    Auto merged
    MERGE: 1.290.85.7

  sql/mysqld.cc@stripped, 2007-02-14 14:51:46+01:00, msvensson@stripped +2 -3
    Manual merge of OPT_SECUREE_FILE_PRIV
    MERGE: 1.439.82.16

  sql/set_var.cc@stripped, 2007-02-14 14:51:46+01:00, msvensson@stripped +0 -2
    Manual merge
    MERGE: 1.125.22.3

  sql/share/errmsg.txt@stripped, 2007-02-14 14:51:47+01:00, msvensson@stripped +0 -1
    Manual merge, change is already in 5.1
    MERGE: 1.42.1.34

  sql/sql_class.cc@stripped, 2007-02-14 14:46:10+01:00, msvensson@stripped +0 -0
    Auto merged
    MERGE: 1.223.18.2

  sql/sql_class.h@stripped, 2007-02-14 14:51:47+01:00, msvensson@stripped +0 -1
    Manual mergem change is already in 5.1 
    MERGE: 1.230.54.1

  sql/sql_load.cc@stripped, 2007-02-14 14:46:10+01:00, msvensson@stripped +0 -0
    Auto merged
    MERGE: 1.78.5.3

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	msvensson
# Host:	pilot.mysql.com
# Root:	/home/msvensson/mysql/mysql-5.1-new-maint/RESYNC

--- 1.309/sql/item_strfunc.cc	2007-01-29 00:51:38 +01:00
+++ 1.310/sql/item_strfunc.cc	2007-02-14 14:46:09 +01:00
@@ -2803,6 +2803,11 @@
   (void) fn_format(path, file_name->c_ptr(), mysql_real_data_home, "",
 		   MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
 
+  /* Read only allowed from within dir specified by secure_file_priv */
+  if (opt_secure_file_priv &&
+      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
+    goto err;
+
   if (!my_stat(path, &stat_info, MYF(0)))
     goto err;
 

--- 1.480/sql/mysql_priv.h	2007-02-13 16:23:29 +01:00
+++ 1.481/sql/mysql_priv.h	2007-02-14 14:46:09 +01:00
@@ -1604,6 +1604,7 @@
 extern my_bool opt_readonly, lower_case_file_system;
 extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs;
 extern my_bool opt_secure_auth;
+extern char* opt_secure_file_priv;
 extern my_bool opt_log_slow_admin_statements;
 extern my_bool sp_automatic_privileges, opt_noacl;
 extern my_bool opt_old_style_user_limits, trust_function_creators;

--- 1.618/sql/mysqld.cc	2007-02-09 00:02:51 +01:00
+++ 1.619/sql/mysqld.cc	2007-02-14 14:51:46 +01:00
@@ -430,6 +430,7 @@
 my_bool opt_readonly, use_temp_pool, relay_log_purge;
 my_bool opt_sync_frm, opt_allow_suspicious_udfs;
 my_bool opt_secure_auth= 0;
+char* opt_secure_file_priv= 0;
 my_bool opt_log_slow_admin_statements= 0;
 my_bool lower_case_file_system= 0;
 my_bool opt_large_pages= 0;
@@ -1233,6 +1234,7 @@
 #endif
   x_free(opt_bin_logname);
   x_free(opt_relay_logname);
+  x_free(opt_secure_file_priv);
   bitmap_free(&temp_pool);
   free_max_user_conn();
 #ifdef HAVE_REPLICATION
@@ -4895,7 +4897,8 @@
   OPT_GENERAL_LOG,
   OPT_SLOW_LOG,
   OPT_MERGE,
-  OPT_INNODB_ROLLBACK_ON_TIMEOUT
+  OPT_INNODB_ROLLBACK_ON_TIMEOUT,
+  OPT_SECURE_FILE_PRIV
 };
 
 
@@ -5598,6 +5601,10 @@
   {"secure-auth", OPT_SECURE_AUTH, "Disallow authentication for accounts that have old (pre-4.1) passwords.",
    (gptr*) &opt_secure_auth, (gptr*) &opt_secure_auth, 0, GET_BOOL, NO_ARG,
    my_bool(0), 0, 0, 0, 0, 0},
+  {"secure-file-priv", OPT_SECURE_FILE_PRIV,
+   "Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory",
+   (gptr*) &opt_secure_file_priv, (gptr*) &opt_secure_file_priv, 0,
+   GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"server-id",	OPT_SERVER_ID,
    "Uniquely identifies the server instance in the community of replication partners.",
    (gptr*) &server_id, (gptr*) &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0,
@@ -6964,6 +6971,7 @@
   opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0;
   opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
   opt_secure_auth= 0;
+  opt_secure_file_priv= 0;
   opt_bootstrap= opt_myisam_log= 0;
   mqh_used= 0;
   segfaulted= kill_in_progress= 0;
@@ -7984,6 +7992,16 @@
       exit(1);
   }
 #endif /* HAVE_REPLICATION */
+  /*
+    Convert the secure-file-priv option to system format, allowing
+    a quick strcmp to check if read or write is in an allowed dir
+   */
+  if (opt_secure_file_priv)
+  {
+    convert_dirname(buff, opt_secure_file_priv, NullS);
+    my_free(opt_secure_file_priv, MYF(0));
+    opt_secure_file_priv= my_strdup(buff, MYF(MY_FAE));
+  }
 }
 
 

--- 1.312/sql/sql_class.cc	2007-02-02 23:22:14 +01:00
+++ 1.313/sql/sql_class.cc	2007-02-14 14:46:10 +01:00
@@ -1179,7 +1179,7 @@
 			IO_CACHE *cache)
 {
   File file;
-  uint option= MY_UNPACK_FILENAME;
+  uint option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
 
 #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
   option|= MY_REPLACE_DIR;			// Force use of db directory
@@ -1193,7 +1193,15 @@
   }
   else
     (void) fn_format(path, exchange->file_name, mysql_real_data_home, "", option);
-    
+
+  if (opt_secure_file_priv &&
+      strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
+  {
+    /* Write only allowed to dir or subdir specified by secure_file_priv */
+    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
+    return -1;
+  }
+
   if (!access(path, F_OK))
   {
     my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);

--- 1.339/sql/sql_class.h	2007-01-29 00:51:39 +01:00
+++ 1.340/sql/sql_class.h	2007-02-14 14:51:47 +01:00
@@ -1640,7 +1640,7 @@
 
 
 /*
-  Used to hold information about file and file structure in exchainge 
+  Used to hold information about file and file structure in exchange
   via non-DB file (...INTO OUTFILE..., ...LOAD DATA...)
   XXX: We never call destructor for objects of this class.
 */

--- 1.114/sql/sql_load.cc	2007-01-24 18:57:00 +01:00
+++ 1.115/sql/sql_load.cc	2007-02-14 14:46:10 +01:00
@@ -305,6 +305,15 @@
       if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
 	is_fifo = 1;
 #endif
+
+      if (opt_secure_file_priv &&
+          strncmp(opt_secure_file_priv, name, strlen(opt_secure_file_priv)))
+      {
+        /* Read only allowed from within dir specified by secure_file_priv */
+        my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
+        DBUG_RETURN(TRUE);
+      }
+
     }
     if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
       DBUG_RETURN(TRUE);

--- 1.270/mysql-test/mysql-test-run.pl	2007-02-06 16:38:53 +01:00
+++ 1.271/mysql-test/mysql-test-run.pl	2007-02-14 14:46:09 +01:00
@@ -3596,6 +3596,12 @@
   mtr_add_arg($args, "%s--basedir=%s", $prefix, $path_my_basedir);
   mtr_add_arg($args, "%s--character-sets-dir=%s", $prefix, $path_charsetsdir);
 
+  if ( $mysql_version_id >= 50036)
+  {
+    # Prevent the started mysqld to access files outside of vardir
+    mtr_add_arg($args, "%s--secure-file-priv=%s", $prefix, $opt_vardir);
+  }
+
   if ( $mysql_version_id >= 50000 )
   {
     mtr_add_arg($args, "%s--log-bin-trust-function-creators", $prefix);

--- 1.56/mysql-test/r/type_blob.result	2006-10-04 16:33:24 +02:00
+++ 1.57/mysql-test/r/type_blob.result	2007-02-14 14:46:09 +01:00
@@ -506,26 +506,26 @@
 Warnings:
 Warning	1101	BLOB/TEXT column 'imagem' can't have a default value
 insert into t1 (id) values (1);
-select 
-charset(load_file('../../std_data/words.dat')),
-collation(load_file('../../std_data/words.dat')),
-coercibility(load_file('../../std_data/words.dat'));
-charset(load_file('../../std_data/words.dat'))	collation(load_file('../../std_data/words.dat'))	coercibility(load_file('../../std_data/words.dat'))
+select
+charset(load_file('../std_data_ln/words.dat')),
+collation(load_file('../std_data_ln/words.dat')),
+coercibility(load_file('../std_data_ln/words.dat'));
+charset(load_file('../std_data_ln/words.dat'))	collation(load_file('../std_data_ln/words.dat'))	coercibility(load_file('../std_data_ln/words.dat'))
 binary	binary	4
-explain extended select 
-charset(load_file('../../std_data/words.dat')),
-collation(load_file('../../std_data/words.dat')),
-coercibility(load_file('../../std_data/words.dat'));
+explain extended select
+charset(load_file('MYSQLTEST_VARDIR/std_data_ln/words.dat')),
+collation(load_file('MYSQLTEST_VARDIR/std_data_ln/words.dat')),
+coercibility(load_file('MYSQLTEST_VARDIR/std_data_ln/words.dat'));
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 Warnings:
-Note	1003	select charset(load_file(_latin1'../../std_data/words.dat')) AS `charset(load_file('../../std_data/words.dat'))`,collation(load_file(_latin1'../../std_data/words.dat')) AS `collation(load_file('../../std_data/words.dat'))`,coercibility(load_file(_latin1'../../std_data/words.dat')) AS `coercibility(load_file('../../std_data/words.dat'))`
-update t1 set imagem=load_file('../../std_data/words.dat') where id=1;
+Note	1003	select charset(load_file(_latin1'MYSQLTEST_VARDIR/std_data_ln/words.dat')) AS `charset(load_file('MYSQLTEST_VARDIR/std_data_ln/words.dat'))`,collation(load_file(_latin1'MYSQLTEST_VARDIR/std_data_ln/words.dat')) AS `collation(load_file('MYSQLTEST_VARDIR/std_data_ln/words.dat'))`,coercibility(load_file(_latin1'MYSQLTEST_VARDIR/std_data_ln/words.dat')) AS `coercibility(load_file('MYSQLTEST_VARDIR/std_data_ln/words.dat'))`
+update t1 set imagem=load_file('MYSQLTEST_VARDIR/std_data_ln/words.dat') where id=1;
 select if(imagem is null, "ERROR", "OK"),length(imagem) from t1 where id = 1;
 if(imagem is null, "ERROR", "OK")	length(imagem)
 OK	581
 drop table t1;
-create table t1 select load_file('../../std_data/words.dat') l;
+create table t1 select load_file('MYSQLTEST_VARDIR/std_data_ln/words.dat') l;
 show full fields from t1;
 Field	Type	Collation	Null	Key	Default	Extra	Privileges	Comment
 l	longblob	NULL	YES		NULL		#	

--- 1.34/mysql-test/t/type_blob.test	2007-01-22 17:42:49 +01:00
+++ 1.35/mysql-test/t/type_blob.test	2007-02-14 14:46:09 +01:00
@@ -307,22 +307,21 @@
 create table t1 (id integer auto_increment unique,imagem LONGBLOB not null default '');
 insert into t1 (id) values (1);
 # We have to clean up the path in the results for safe comparison
---replace_result $MYSQL_TEST_DIR ../..
-eval select 
-  charset(load_file('$MYSQL_TEST_DIR/std_data/words.dat')),
-  collation(load_file('$MYSQL_TEST_DIR/std_data/words.dat')),
-  coercibility(load_file('$MYSQL_TEST_DIR/std_data/words.dat'));
---replace_result $MYSQL_TEST_DIR ../..
-eval explain extended select 
-  charset(load_file('$MYSQL_TEST_DIR/std_data/words.dat')),
-  collation(load_file('$MYSQL_TEST_DIR/std_data/words.dat')),
-  coercibility(load_file('$MYSQL_TEST_DIR/std_data/words.dat'));
---replace_result $MYSQL_TEST_DIR ../..
-eval update t1 set imagem=load_file('$MYSQL_TEST_DIR/std_data/words.dat') where id=1;
+eval select
+  charset(load_file('../std_data_ln/words.dat')),
+  collation(load_file('../std_data_ln/words.dat')),
+  coercibility(load_file('../std_data_ln/words.dat'));
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval explain extended select
+  charset(load_file('$MYSQLTEST_VARDIR/std_data_ln/words.dat')),
+  collation(load_file('$MYSQLTEST_VARDIR/std_data_ln/words.dat')),
+  coercibility(load_file('$MYSQLTEST_VARDIR/std_data_ln/words.dat'));
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval update t1 set imagem=load_file('$MYSQLTEST_VARDIR/std_data_ln/words.dat') where id=1;
 select if(imagem is null, "ERROR", "OK"),length(imagem) from t1 where id = 1;
 drop table t1;
---replace_result $MYSQL_TEST_DIR ../..
-eval create table t1 select load_file('$MYSQL_TEST_DIR/std_data/words.dat') l;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval create table t1 select load_file('$MYSQLTEST_VARDIR/std_data_ln/words.dat') l;
 # We mask out the Privileges column because it differs for embedded server
 --replace_column 8 #
 show full fields from t1;

--- 1.84/mysql-test/r/query_cache.result	2006-11-29 15:28:31 +01:00
+++ 1.85/mysql-test/r/query_cache.result	2007-02-14 14:46:09 +01:00
@@ -624,7 +624,7 @@
 show status like "Qcache_queries_in_cache";
 Variable_name	Value
 Qcache_queries_in_cache	1
-load data infile 'TEST_DIR/std_data/words.dat' into table t1;
+load data infile 'MYSQLTEST_VARDIR/std_data_ln/words.dat' into table t1;
 show status like "Qcache_queries_in_cache";
 Variable_name	Value
 Qcache_queries_in_cache	0

--- 1.65/mysql-test/t/query_cache.test	2006-11-29 15:28:31 +01:00
+++ 1.66/mysql-test/t/query_cache.test	2007-02-14 14:46:09 +01:00
@@ -409,8 +409,8 @@
 create table t1 (word char(20) not null);
 select * from t1;
 show status like "Qcache_queries_in_cache";
---replace_result $MYSQL_TEST_DIR TEST_DIR
-eval load data infile '$MYSQL_TEST_DIR/std_data/words.dat' into table t1;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+eval load data infile '$MYSQLTEST_VARDIR/std_data_ln/words.dat' into table t1;
 show status like "Qcache_queries_in_cache";
 select count(*) from t1;
 drop table t1;

--- 1.215/sql/set_var.cc	2007-02-06 15:52:25 +01:00
+++ 1.216/sql/set_var.cc	2007-02-14 14:51:46 +01:00
@@ -411,6 +411,8 @@
 				 &SV::query_cache_wlock_invalidate);
 #endif /* HAVE_QUERY_CACHE */
 sys_var_bool_ptr	sys_secure_auth("secure_auth", &opt_secure_auth);
+sys_var_const_str_ptr   sys_secure_file_priv("secure_file_priv",
+                                             &opt_secure_file_priv);
 sys_var_long_ptr	sys_server_id("server_id", &server_id, fix_server_id);
 sys_var_bool_ptr	sys_slave_compressed_protocol("slave_compressed_protocol",
 						      &opt_slave_compressed_protocol);
@@ -669,7 +671,6 @@
 sys_var_have_variable sys_have_symlink("have_symlink", &have_symlink);
 /* Global read-only variable describing server license */
 sys_var_const_str		sys_license("license", STRINGIFY_ARG(LICENSE));
-
 /* Global variables which enable|disable logging */
 sys_var_log_state sys_var_general_log("general_log", &opt_log,
                                       QUERY_LOG_GENERAL);
@@ -959,6 +960,7 @@
 #endif
   {sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank,       SHOW_SYS},
   {"secure_auth",             (char*) &sys_secure_auth,             SHOW_SYS},
+  {"secure_file_priv",        (char*) &sys_secure_file_priv,        SHOW_SYS},
 #ifdef HAVE_SMEM
   {"shared_memory",           (char*) &opt_enable_shared_memory,    SHOW_MY_BOOL},
   {"shared_memory_base_name", (char*) &shared_memory_base_name,     SHOW_CHAR_PTR},

--- 1.27/mysql-test/r/loaddata.result	2006-10-03 13:00:03 +02:00
+++ 1.28/mysql-test/r/loaddata.result	2007-02-14 14:46:09 +01:00
@@ -148,6 +148,22 @@
 a	b	c
 10	NULL	Ten
 15	NULL	Fifteen
+show variables like "secure_file_pri%";
+Variable_name	Value
+secure_file_priv	MYSQLTEST_VARDIR/
+select @@secure_file_priv;
+@@secure_file_priv
+MYSQLTEST_VARDIR/
+set @@secure_file_priv= 0;
+ERROR HY000: Variable 'secure_file_priv' is a read only variable
+truncate table t1;
+load data infile 'MYSQL_TEST_DIR/Makefile' into table t1;
+ERROR HY000: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
+select * from t1;
+a	b	c
+select load_file("MYSQL_TEST_DIR/Makefile");
+load_file("MYSQL_TEST_DIR/Makefile")
+NULL
 drop table t1, t2;
 CREATE TABLE t1 (a int);
 INSERT INTO t1 VALUES (1);

--- 1.21/mysql-test/t/loaddata.test	2006-06-04 17:52:06 +02:00
+++ 1.22/mysql-test/t/loaddata.test	2007-02-14 14:46:09 +01:00
@@ -114,6 +114,29 @@
 load data infile '../std_data_ln/rpl_loaddata.dat' into table t1 (@dummy,@n) set a= @n, c= (select str from t2 where num=@n);
 select * from t1;
 
+#
+# Bug#18628 mysql-test-run: security problem
+#
+# It should not be possible to load from a file outside of vardir
+
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+show variables like "secure_file_pri%";
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+select @@secure_file_priv;
+--error 1238
+set @@secure_file_priv= 0;
+
+# Test "load data"
+truncate table t1;
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--error 1290
+eval load data infile '$MYSQL_TEST_DIR/Makefile' into table t1;
+select * from t1;
+
+# Test "load_file" returns NULL
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+eval select load_file("$MYSQL_TEST_DIR/Makefile");
+
 # cleanup
 drop table t1, t2;
 
Thread
bk commit into 5.1 tree (msvensson:1.2435)msvensson14 Feb