List:Commits« Previous MessageNext Message »
From:Jorgen Loland Date:August 27 2008 9:26am
Subject:bzr commit into mysql-6.0-backup branch (jorgen.loland:2683) Bug#34171
View as plain text  
#At file:///localhome/jl208045/mysql/mysql-6.0-backup-34171/

 2683 Jorgen Loland	2008-08-27
      Bug#34171 - "Backup: ignoring --secure-file-priv"
                  
      Before patch: Backup code ignored secure-file-priv option, 
      allowing backup to write to any location
                  
      After patch: Backup and restore are not allowed to write or read 
      outside path in secure-file-priv option if option has been 
      specified.
added:
  mysql-test/r/backup_securefilepriv.result
  mysql-test/t/backup_securefilepriv-master.opt
  mysql-test/t/backup_securefilepriv.test
modified:
  mysql-test/lib/mtr_report.pl
  mysql-test/r/backup_backupdir.result
  mysql-test/t/backup_backupdir.test
  sql/backup/backup_kernel.h
  sql/backup/kernel.cc
  sql/backup/stream.cc
  sql/backup/stream.h

per-file comments:
  mysql-test/lib/mtr_report.pl
    Added expected error for backup_securefilepriv
  mysql-test/r/backup_backupdir.result
    Result modified to handle modified test file due to secure-file-priv
  mysql-test/r/backup_securefilepriv.result
    New result file for secure-file-priv backup tests
  mysql-test/t/backup_backupdir.test
    Tests modified to handle secure-file-priv
  mysql-test/t/backup_securefilepriv-master.opt
    Sets secure-file-priv option for backup_securefilepriv test
  mysql-test/t/backup_securefilepriv.test
    New test file for secure-file-priv backup tests
  sql/backup/backup_kernel.h
    Added private function report_stream_open_failure
  sql/backup/kernel.cc
    Improved error handling for errors reported by *Stream::open
  sql/backup/stream.cc
    Adds check for secure-file-priv option when opening backup/restore streams. Also some documentation bug fixes for Stream::prepare_path
  sql/backup/stream.h
    Added private method test_secure_file_priv_access, *Stream::open() now returns int
=== modified file 'mysql-test/lib/mtr_report.pl'
--- a/mysql-test/lib/mtr_report.pl	2008-08-20 13:23:10 +0000
+++ b/mysql-test/lib/mtr_report.pl	2008-08-27 09:26:33 +0000
@@ -357,6 +357,12 @@ sub mtr_report_stats ($) {
 		(
 		  /Restore: Tablespace .* needed by tables being restored has changed on the server/
 		) or
+                
+		# The backup_securefilepriv test triggers error below on purpose
+		($testname eq 'main.backup_securefilepriv') and
+		(
+		  /Backup: The MySQL server is running with the /
+		) or
 		
 		# The views test triggers errors below on purpose
 		($testname eq 'main.backup_views') and

=== modified file 'mysql-test/r/backup_backupdir.result'
--- a/mysql-test/r/backup_backupdir.result	2008-08-08 17:21:31 +0000
+++ b/mysql-test/r/backup_backupdir.result	2008-08-27 09:26:33 +0000
@@ -41,11 +41,16 @@ backup_id
 #
 Ensure backup image file went to the correct location
 Try a backup to an invalid relative path.
-BACKUP DATABASE bup_backupdir TO '../../../../../../../../../../../../../../../../../../bup_backupdir5.bak';
-ERROR HY000: Can't write to backup location '../../../../../../../../../../../../../../../../../../bup_backup' (file already exists?)
+BACKUP DATABASE bup_backupdir TO '../not/there/bup_backupdir5.bak';
+ERROR HY000: Can't write to backup location '../not/there/bup_backupdir5.bak' (file already exists?)
+
 Try a backup to an invalid hard path.
-BACKUP DATABASE bup_backupdir TO '/dev/not/there/either/bup_backupdir6.bak';
-ERROR HY000: Can't write to backup location '/dev/not/there/either/bup_backupdir6.bak' (file already exists?)
+*Actual BACKUP DATABASE command not printed due to non-deterministic path.
+*Performing: 
+*BACKUP DATABASE bup_backupdir TO '$MYSQLTEST_VARDIR/master_data/not/there/either/bup_backupdir6.bak';
+ERROR HY000: Can't write to backup location '$MYSQLTEST_VARDIR/master_data/not/there/either/bup_backupdir6.bak' (file already exists?)
+
+Attempt to set the backupdir to something invalid.
 SET @@global.backupdir = 'This_is_really_stupid/not/there/at/all';
 Warnings:
 Warning	1725	The path specified for the system variable backupdir cannot be accessed or is invalid. ref: This_is_really_stupid/not/there/at/all

=== added file 'mysql-test/r/backup_securefilepriv.result'
--- a/mysql-test/r/backup_securefilepriv.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/backup_securefilepriv.result	2008-08-27 09:26:33 +0000
@@ -0,0 +1,60 @@
+Initializing tests
+Create directories for backup images
+Creating database and populating tables
+DROP DATABASE IF EXISTS mysqltest;
+CREATE DATABASE mysqltest;
+CREATE TABLE mysqltest.t1 (i int);
+INSERT INTO mysqltest.t1 VALUES (1),(2),(3),(4),(5),(10),(15),(100);
+
+Starting tests
+
+Backup to path specified by --secure-file-priv option
+(MYSQLTEST_VARDIR/master-data/securefilepriv_path)
+BACKUP DATABASE mysqltest TO 'securefilepriv_path/bup_sfp1.bak';
+backup_id
+#
+Ensure backup image file went to the correct location
+
+Backup to subpath of path specified by --secure-file-priv option
+(MYSQLTEST_VARDIR/master-data/securefilepriv_path/subpath)
+BACKUP DATABASE mysqltest TO 'securefilepriv_path/subpath/bup_sfp2.bak';
+backup_id
+#
+Ensure backup image file went to the correct location
+
+Change backupdir to securefilepriv_path/subpath 
+(MYSQLTEST_VARDIR/master-data/securefilepriv_path/subpath)
+SET @@global.backupdir = 'securefilepriv_path/subpath';
+
+Backup to subpath of path specified by --secure-file-priv option, 
+no dir in backup file name
+(MYSQLTEST_VARDIR/master-data/securefilepriv_path/subpath)
+BACKUP DATABASE mysqltest TO 'bup_sfp3.bak';
+backup_id
+#
+Ensure backup image file went to the correct location
+
+Backup to path specified by --secure-file-priv, 
+relative path in backup file name
+(MYSQLTEST_VARDIR/master-data/securefilepriv_path)
+BACKUP DATABASE mysqltest TO '../bup_sfp4.bak';
+backup_id
+#
+Ensure backup image file went to the correct location
+
+Backup to relative path outside path specified by --secure-file-priv 
+option should fail
+BACKUP DATABASE mysqltest TO '../../bup_sfp_fail1.bak';
+ERROR HY000: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
+
+Reset backupdir to MYSQLTEST_VARDIR/master-data/
+SET @@global.backupdir = @@global.datadir;
+
+Backup to other path than specified by --secure-file-priv should fail
+BACKUP DATABASE mysqltest TO 'bup_sfp_fail2.bak';
+ERROR HY000: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
+
+Cleanup
+
+DROP TABLE mysqltest.t1;
+DROP DATABASE mysqltest;

=== modified file 'mysql-test/t/backup_backupdir.test'
--- a/mysql-test/t/backup_backupdir.test	2008-08-08 17:21:31 +0000
+++ b/mysql-test/t/backup_backupdir.test	2008-08-27 09:26:33 +0000
@@ -75,15 +75,24 @@ BACKUP DATABASE bup_backupdir TO '../../
 
 --echo Try a backup to an invalid relative path.
 --error ER_BACKUP_WRITE_LOC
-BACKUP DATABASE bup_backupdir TO '../../../../../../../../../../../../../../../../../../bup_backupdir5.bak';
+BACKUP DATABASE bup_backupdir TO '../not/there/bup_backupdir5.bak';
 
+--echo 
 --echo Try a backup to an invalid hard path.
+
+--echo *Actual BACKUP DATABASE command not printed due to non-deterministic path.
+--echo *Performing: 
+--echo *BACKUP DATABASE bup_backupdir TO '\$MYSQLTEST_VARDIR/master_data/not/there/either/bup_backupdir6.bak';
+# Do not print the SQL command to result file because dir is not deterministic across hosts
+--disable_query_log
+# Replace actual dir in error message because $MYSQLTEST_VARDIR is not deterministic
+replace_regex /(location ').*'/location '$MYSQLTEST_VARDIR\/master_data\/not\/there\/either\/bup_backupdir6.bak'/ ;
 --error ER_BACKUP_WRITE_LOC
-BACKUP DATABASE bup_backupdir TO '/dev/not/there/either/bup_backupdir6.bak';
+--eval BACKUP DATABASE bup_backupdir TO '$MYSQLTEST_VARDIR/master_data/not/there/either/bup_backupdir6.bak';
+--enable_query_log
 
-#
-# Attempt to set the backupdir to something invalid.
-#
+--echo
+--echo Attempt to set the backupdir to something invalid.
 SET @@global.backupdir = 'This_is_really_stupid/not/there/at/all';
 
 --echo Cleanup

=== added file 'mysql-test/t/backup_securefilepriv-master.opt'
--- a/mysql-test/t/backup_securefilepriv-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/backup_securefilepriv-master.opt	2008-08-27 09:26:33 +0000
@@ -0,0 +1 @@
+--secure-file-priv=$MYSQLTEST_VARDIR/master-data/securefilepriv_path

=== added file 'mysql-test/t/backup_securefilepriv.test'
--- a/mysql-test/t/backup_securefilepriv.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/backup_securefilepriv.test	2008-08-27 09:26:33 +0000
@@ -0,0 +1,118 @@
+#
+# Purpose: Backup images should only be allowed to be written to the
+# path specified by --secure-file-priv option or a sub-path of it.
+#
+# See backup_securefilepriv-master.opt for --secure-file-priv command line option
+#
+# backupdir        is MYSQLTEST_VARDIR/master-data/
+# secure-file-priv is MYSQLTEST_VARDIR/master-data/securefilepriv_path/
+
+--echo Initializing tests
+
+--error 0,1
+rmdir $MYSQLTEST_VARDIR/master-data/securefilepriv_path/subpath;
+--error 0,1
+rmdir $MYSQLTEST_VARDIR/master-data/securefilepriv_path;
+
+--echo Create directories for backup images
+mkdir $MYSQLTEST_VARDIR/master-data/securefilepriv_path;
+mkdir $MYSQLTEST_VARDIR/master-data/securefilepriv_path/subpath;
+
+--echo Creating database and populating tables
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest;
+--enable_warnings
+
+CREATE DATABASE mysqltest;
+
+CREATE TABLE mysqltest.t1 (i int);
+
+INSERT INTO mysqltest.t1 VALUES (1),(2),(3),(4),(5),(10),(15),(100);
+
+--echo 
+--echo Starting tests
+
+--echo 
+--echo Backup to path specified by --secure-file-priv option
+--echo (MYSQLTEST_VARDIR/master-data/securefilepriv_path)
+--replace_column 1 #
+BACKUP DATABASE mysqltest TO 'securefilepriv_path/bup_sfp1.bak';
+
+--echo Ensure backup image file went to the correct location
+--file_exists $MYSQLTEST_VARDIR/master-data/securefilepriv_path/bup_sfp1.bak
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/securefilepriv_path/bup_sfp1.bak
+
+--echo  
+--echo Backup to subpath of path specified by --secure-file-priv option
+--echo (MYSQLTEST_VARDIR/master-data/securefilepriv_path/subpath)
+--replace_column 1 #
+BACKUP DATABASE mysqltest TO 'securefilepriv_path/subpath/bup_sfp2.bak';
+
+--echo Ensure backup image file went to the correct location
+--file_exists $MYSQLTEST_VARDIR/master-data/securefilepriv_path/subpath/bup_sfp2.bak
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/securefilepriv_path/subpath/bup_sfp2.bak
+
+--echo  
+--echo Change backupdir to securefilepriv_path/subpath 
+--echo (MYSQLTEST_VARDIR/master-data/securefilepriv_path/subpath)
+SET @@global.backupdir = 'securefilepriv_path/subpath';
+
+--echo  
+--echo Backup to subpath of path specified by --secure-file-priv option, 
+--echo no dir in backup file name
+--echo (MYSQLTEST_VARDIR/master-data/securefilepriv_path/subpath)
+--replace_column 1 #
+BACKUP DATABASE mysqltest TO 'bup_sfp3.bak';
+
+--echo Ensure backup image file went to the correct location
+--file_exists $MYSQLTEST_VARDIR/master-data/securefilepriv_path/subpath/bup_sfp3.bak
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/securefilepriv_path/subpath/bup_sfp3.bak
+
+--echo  
+--echo Backup to path specified by --secure-file-priv, 
+--echo relative path in backup file name
+--echo (MYSQLTEST_VARDIR/master-data/securefilepriv_path)
+--replace_column 1 #
+BACKUP DATABASE mysqltest TO '../bup_sfp4.bak';
+
+--echo Ensure backup image file went to the correct location
+--file_exists $MYSQLTEST_VARDIR/master-data/securefilepriv_path/bup_sfp4.bak
+
+--error 0,1
+--remove_file $MYSQLTEST_VARDIR/master-data/securefilepriv_path/bup_sfp4.bak
+
+# Tests that fail
+
+--echo  
+--echo Backup to relative path outside path specified by --secure-file-priv 
+--echo option should fail
+--error ER_OPTION_PREVENTS_STATEMENT
+BACKUP DATABASE mysqltest TO '../../bup_sfp_fail1.bak';
+
+--echo  
+--echo Reset backupdir to MYSQLTEST_VARDIR/master-data/
+SET @@global.backupdir = @@global.datadir;
+
+--echo  
+--echo Backup to other path than specified by --secure-file-priv should fail
+--error ER_OPTION_PREVENTS_STATEMENT
+BACKUP DATABASE mysqltest TO 'bup_sfp_fail2.bak';
+
+--echo 
+--echo Cleanup
+--echo 
+
+DROP TABLE mysqltest.t1;
+DROP DATABASE mysqltest;
+
+--error 0,1,2
+rmdir $MYSQLTEST_VARDIR/master-data/securefilepriv_path/subpath;
+--error 0,1,2
+rmdir $MYSQLTEST_VARDIR/master-data/securefilepriv_path;

=== modified file 'sql/backup/backup_kernel.h'
--- a/sql/backup/backup_kernel.h	2008-08-08 17:21:31 +0000
+++ b/sql/backup/backup_kernel.h	2008-08-27 09:26:33 +0000
@@ -129,6 +129,8 @@ class Backup_restore_ctx: public backup:
   int lock_tables_for_restore();
   int unlock_tables();
   
+  int report_stream_open_failure(int open_error, LEX_STRING location);
+
   friend class Backup_info;
   friend class Restore_info;
   friend int backup_init();

=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc	2008-08-21 11:36:09 +0000
+++ b/sql/backup/kernel.cc	2008-08-27 09:26:33 +0000
@@ -551,13 +551,10 @@ Backup_restore_ctx::prepare_for_backup(S
     return NULL;
   }
   
-  if (!s->open())
+  int my_open_status= s->open();
+  if (my_open_status != 0)
   {
-    /*
-      For this error, use the actual value returned instead of the
-      path complimented with backupdir.
-    */
-    fatal_error(ER_BACKUP_WRITE_LOC, orig_loc.str);
+    report_stream_open_failure(my_open_status, orig_loc);
     return NULL;
   }
 
@@ -634,13 +631,10 @@ Backup_restore_ctx::prepare_for_restore(
     return NULL;
   }
   
-  if (!s->open())
+  int my_open_status= s->open();
+  if (my_open_status != 0)
   {
-    /*
-      For this error, use the actual value returned instead of the
-      path complimented with backupdir.
-    */
-    fatal_error(ER_BACKUP_READ_LOC, orig_loc.str);
+    report_stream_open_failure(my_open_status, orig_loc);
     return NULL;
   }
 
@@ -1130,6 +1124,40 @@ int Backup_restore_ctx::do_restore()
   DBUG_RETURN(0);
 }
 
+/**
+  Report stream open error by calling fatal_error, effectively moving
+  context object into error state.
+  
+  @return error code given as input or the one stored in the context
+  object if a fatal error has already been reported.
+ */ 
+int Backup_restore_ctx::report_stream_open_failure(int my_open_status,
+                                                   LEX_STRING location)
+{
+  int error= 0;
+  switch (my_open_status) {
+    case ER_OPTION_PREVENTS_STATEMENT:
+      error= fatal_error(ER_OPTION_PREVENTS_STATEMENT, "--secure-file-priv");
+      break;
+    case ER_BACKUP_WRITE_LOC:
+      /*
+        For this error, use the actual value returned instead of the
+        path complimented with backupdir.
+      */
+      error= fatal_error(ER_BACKUP_WRITE_LOC, location.str);
+      break;
+    case ER_BACKUP_READ_LOC:
+      /*
+        For this error, use the actual value returned instead of the
+        path complimented with backupdir.
+      */
+      error= fatal_error(ER_BACKUP_READ_LOC, location.str);
+      break;
+    default:
+      DBUG_ASSERT(FALSE);
+  }
+  return error;
+}
 
 namespace backup {
 

=== modified file 'sql/backup/stream.cc'
--- a/sql/backup/stream.cc	2008-08-08 17:21:31 +0000
+++ b/sql/backup/stream.cc	2008-08-27 09:26:33 +0000
@@ -218,6 +218,9 @@ Stream::Stream(Logger &log, ::String *ba
   For example, if backupdir = '/dev/tmp' and orig_log = '../backup.bak', the 
   combined path is = '/dev/backup.bak'.
 
+  Note: fn_format may likely be used instead of this function - will
+  not be changed unless bugs are found.
+
   @returns 
     0 if success
     1 if cannot be combined. Note: m_path is set to '' when this occurs to
@@ -289,6 +292,31 @@ int Stream::prepare_path(::String *backu
   int path_len= 0;
 
   /*
+    The full path is needed to test for secure-file-priv option in
+    Stream::open. If not full, replace backupdir with the full
+    path name, which is relative to datadir (i.e., global variable
+    mysql_real_data_home)
+  */
+  if (!test_if_hard_path(backupdir->c_ptr()))
+  {
+    char full_path[FN_LEN];
+    
+    /* 
+       MY_UNPACK_FILENAME  "~/" will be changed to full path
+       MY_RELATIVE_PATH    path is constructed from the base path
+                           mysql_real_data_home combined with the
+                           relative path backupdir. Also handles
+                           "../" in backupdir and converts dirname 
+                           to fit this system
+    */
+    fn_format(full_path, backupdir->c_ptr(), mysql_real_data_home, "",
+              MY_UNPACK_FILENAME | MY_RELATIVE_PATH);
+
+    uint32 full_path_len= strlen(full_path);
+    (*backupdir).copy(full_path, full_path_len, &::my_charset_bin);
+  }
+  
+  /*
     Prepare the path using the backupdir iff no relative path
     or no hard path included.
 
@@ -301,9 +329,9 @@ int Stream::prepare_path(::String *backu
               Make relative to backupdir.
 
       Example BACKUP DATATBASE ... TO '../monthly/dec.bak'
-              If backupdir = '/dev/daily/backup' then the
+              If backupdir = '/dev/daily' then the
               calculated path becomes
-              '/dev/monthly/backup/dec.bak'
+              '/dev/monthly/dec.bak'
     */
     char new_path[FN_LEN];
     if (make_relative_path(new_path, orig_loc.str, backupdir))
@@ -316,42 +344,85 @@ int Stream::prepare_path(::String *backu
   else if (!test_if_hard_path(orig_loc.str))
   {
     /* 
-      Case 2: Backup image file name has hard path. 
+      Case 2: Backup image file name has no path or has a subpath. 
 
-      Example BACKUP DATATBASE ... TO '/dev/dec.bak'
-              If backupdir = '/dev/daily/backup' then the
+      Example BACKUP DATABASE ... TO 'week2.bak'
+              If backupdir = '/dev/weekly/' then the
               calculated path becomes
-              '/dev/dec.bak'
+              '/dev/weekly/week2.bak'
+      Example BACKUP DATABASE ... TO 'jan/day1.bak'
+              If backupdir = '/dev/monthly/' then the
+              calculated path becomes
+              '/dev/monthly/jan/day1.bak'
     */
     path_len=backupdir->length() + orig_loc.length + 1;
     m_path.alloc(path_len);
     fn_format(m_path.c_ptr(), orig_loc.str, backupdir->c_ptr(), "",
-              MY_UNPACK_FILENAME);
+              MY_UNPACK_FILENAME | MY_RELATIVE_PATH);
   }
   else 
   {
     /* 
-      Case 3: Backup image file name has no path. 
+      Case 3: Backup image file name has hard path. 
 
-      Example BACKUP DATATBASE ... TO 'week2.bak'
-              If backupdir = '/dev/weekly/backup' then the
+      Example BACKUP DATATBASE ... TO '/dev/dec.bak'
+              If backupdir = '/dev/daily/backup' then the
               calculated path becomes
-              '/dev/weekly/week2.bak'
+              '/dev/dec.bak'
     */
     path_len= orig_loc.length + 1;
     m_path.alloc(path_len);
     m_path.length(0);
     m_path.append(orig_loc.str);
+    // Convert directory name to fit this system
+    convert_dirname(m_path.c_ptr(), orig_loc.str, NullS);
   }
   m_path.length(path_len);
   return 0;
 }
 
-bool Stream::open()
+/**
+  Check if secure-file-priv option has been set and if so, whether
+  or not backup tries to write to the path (or a sub-path) specified
+  by secure-file-priv.
+
+  Reports error ER_OPTION_PREVENTS_STATEMENT if backup tries to write
+  to a different path than specified by secure-file-priv.
+  
+  @retval TRUE  backup is allowed to write to this path
+  @retval FALSE backup is not allowed to write to this path. Side
+                effect: error is reported
+*/
+bool Stream::test_secure_file_priv_access(char *path) {
+  bool has_access = !opt_secure_file_priv ||                 // option not specified, or
+                    !strncmp(opt_secure_file_priv, path,     // path is (subpath of)
+                             strlen(opt_secure_file_priv));  // secure-file-priv option
+   if (!has_access)
+     m_log.report_error(ER_OPTION_PREVENTS_STATEMENT, "--secure-file-priv");
+
+  return has_access;
+}
+
+/**
+   Open a stream.
+
+   @retval 0 if stream was successfully opened
+   @retval ER_OPTION_PREVENTS_STATEMENT if secure-file-priv option
+           prevented stream open from this path
+   @retval -1 if open failed for another reason
+ */
+int Stream::open()
 {
   close();
+  if (!test_secure_file_priv_access(m_path.c_ptr()))
+    return ER_OPTION_PREVENTS_STATEMENT;
+
   m_fd= my_open(m_path.c_ptr(), m_flags, MYF(0));
-  return m_fd >= 0;
+
+  if (!(m_fd >= 0))
+    return -1;
+
+  return 0;
 }
 
 void Stream::close()
@@ -445,12 +516,14 @@ bool Output_stream::init()
 /**
   Open and initialize backup stream for writing.
 
-  @retval TRUE  operation succeeded
-  @retval FALSE operation failed
+  @retval 0                             operation succeeded
+  @retval ER_OPTION_PREVENTS_STATEMENT  secure-file-priv option
+                                        prevented stream open from this path
+  @retval ER_BACKUP_WRITE_LOC           open failed for another reason
 
   @todo Report errors.
 */
-bool Output_stream::open()
+int Output_stream::open()
 {
   MY_STAT stat_info;
   close();
@@ -462,10 +535,10 @@ bool Output_stream::open()
   else
     m_flags= O_WRONLY|O_CREAT|O_EXCL|O_TRUNC;
 
-  bool ret= Stream::open();
+  int ret= Stream::open();
 
-  if (!ret)
-    return FALSE;
+  if (ret != 0)
+    return ret == -1 ? ER_BACKUP_WRITE_LOC : ret;
 
   if (m_with_compression)
   {
@@ -474,7 +547,7 @@ bool Output_stream::open()
     if (!(zbuf= (uchar*) my_malloc(ZBUF_SIZE, MYF(0))))
     {
       m_log.report_error(ER_OUTOFMEMORY, ZBUF_SIZE);
-      return FALSE;
+      return ER_BACKUP_WRITE_LOC;
     }
     zstream.zalloc= 0;
     zstream.zfree= 0;
@@ -488,15 +561,18 @@ bool Output_stream::open()
     {
       m_log.report_error(ER_BACKUP_FAILED_TO_INIT_COMPRESSION,
                          zerr, zstream.msg);
-      return FALSE;
+      return ER_BACKUP_WRITE_LOC;
     }
 #else
     m_log.report_error(ER_FEATURE_DISABLED, "compression", "--with-zlib-dir");
-    return FALSE;
+    return ER_BACKUP_WRITE_LOC;
 #endif
   }
 
-  return init();
+  if (!init())
+    return ER_BACKUP_WRITE_LOC;
+
+  return 0;
 }
 
 /**
@@ -627,23 +703,25 @@ bool Input_stream::init()
   available for reading with stream_read(). Instead, they are stored in
   m_header_buf member and examined by check_magic_and_version().
 
-  @retval TRUE  operation succeeded
-  @retval FALSE operation failed
+  @retval 0                             operation succeeded
+  @retval ER_OPTION_PREVENTS_STATEMENT  secure-file-priv option
+                                        prevented stream open from this path
+  @retval ER_BACKUP_READ_LOC            open failed for another reason
 
   @todo Report errors.
 */
-bool Input_stream::open()
+int Input_stream::open()
 {
   close();
 
-  bool ret= Stream::open();
+  int ret= Stream::open();
 
-  if (!ret)
-    return FALSE;
+  if (ret != 0)
+    return ret == -1 ? ER_BACKUP_READ_LOC : ret;
 
   if (my_read(m_fd, m_header_buf, sizeof(m_header_buf),
               MY_NABP /* error if not all bytes read */ ))
-    return FALSE;
+    return ER_BACKUP_READ_LOC;
 
 #ifdef HAVE_COMPRESS
   if (!memcmp(m_header_buf, "\x1f\x8b\x08", 3))
@@ -653,7 +731,7 @@ bool Input_stream::open()
     if (!(zbuf= (uchar*) my_malloc(ZBUF_SIZE, MYF(0))))
     {
       m_log.report_error(ER_OUTOFMEMORY, ZBUF_SIZE);
-      return FALSE;
+      return ER_BACKUP_WRITE_LOC;
     }
     zstream.zalloc= 0;
     zstream.zfree= 0;
@@ -666,18 +744,21 @@ bool Input_stream::open()
     {
       m_log.report_error(ER_GET_ERRMSG, zerr, zstream.msg, "inflateInit2");
       my_free(zbuf, MYF(0));
-      return FALSE;
+      return ER_BACKUP_READ_LOC;
     }
     m_with_compression= true;
     blob.begin= m_header_buf;
     blob.end= m_header_buf + 10;
     if (stream_read((fd_stream*) this, &blob, blob) != BSTREAM_OK ||
         blob.begin != blob.end)
-      return FALSE;
+      return ER_BACKUP_READ_LOC;
   }
 #endif
 
-  return init();
+  if (!init())
+    return ER_BACKUP_READ_LOC;
+
+  return 0;
 }
 
 /**

=== modified file 'sql/backup/stream.h'
--- a/sql/backup/stream.h	2008-08-08 17:21:31 +0000
+++ b/sql/backup/stream.h	2008-08-27 09:26:33 +0000
@@ -79,7 +79,7 @@ class Stream: public fd_stream
 {
  public:
 
-  bool open();
+  int open();
   virtual void close();
   bool rewind();
 
@@ -109,6 +109,7 @@ private:
                          ::String *backupdir);
   int prepare_path(::String *backupdir, 
                    LEX_STRING orig_loc);
+  bool test_secure_file_priv_access(char *path);
 
 };
 
@@ -120,7 +121,7 @@ class Output_stream:
 
   Output_stream(Logger&, ::String *, LEX_STRING, bool);
 
-  bool open();
+  int  open();
   void close();
   bool rewind();
 
@@ -138,7 +139,7 @@ class Input_stream:
 
   Input_stream(Logger&, ::String *, LEX_STRING);
 
-  bool open();
+  int  open();
   void close();
   bool rewind();
 

Thread
bzr commit into mysql-6.0-backup branch (jorgen.loland:2683) Bug#34171Jorgen Loland27 Aug