diff options
author | unknown <monty@narttu.mysql.fi> | 2003-03-10 11:22:37 +0200 |
---|---|---|
committer | unknown <monty@narttu.mysql.fi> | 2003-03-10 11:22:37 +0200 |
commit | 68ae365395c78eba74b4db66fb0989e76d221d0d (patch) | |
tree | caaf93f4311641760c5a58ab8099d7eab15c0d79 | |
parent | 374ea106f5098e4a6ee79f217bf799d181d20a25 (diff) | |
download | mariadb-git-68ae365395c78eba74b4db66fb0989e76d221d0d.tar.gz |
Don't allow BACKUP TABLE to overwrite files
Fixed memory leak when replication restarts in debug mode
include/my_sys.h:
Added option to not overwrite files to my_copy()
mysql-test/mysql-test-run.sh:
Fixed --ddd option
Fixed that mysqld is restarted if there is a testname-master.sh file
mysql-test/r/backup.result:
Update for security fix in BACKUP TABLE
mysql-test/t/backup.test:
Update for security fix in BACKUP TABLE
mysys/my_copy.c:
Added option to not overwrite files to my_copy()
sql/ha_myisam.cc:
Don't allow BACKUP TABLE to overwrite files
sql/slave.cc:
Fixed problem with --debug output from 'handle_slave'
Fixed memory leak when replication restarts in debug mode
-rw-r--r-- | include/my_sys.h | 1 | ||||
-rw-r--r-- | mysql-test/mysql-test-run.sh | 4 | ||||
-rw-r--r-- | mysql-test/r/backup.result | 14 | ||||
-rwxr-xr-x | mysql-test/t/backup-master.sh | 5 | ||||
-rw-r--r-- | mysql-test/t/backup.test | 39 | ||||
-rw-r--r-- | mysys/my_copy.c | 30 | ||||
-rw-r--r-- | sql/ha_myisam.cc | 42 | ||||
-rw-r--r-- | sql/slave.cc | 34 |
8 files changed, 98 insertions, 71 deletions
diff --git a/include/my_sys.h b/include/my_sys.h index cd6ec62719a..924a6094416 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -73,6 +73,7 @@ extern int NEAR my_errno; /* Last error in mysys */ #define MY_FREE_ON_ERROR 128 /* my_realloc() ; Free old ptr on error */ #define MY_HOLD_ON_ERROR 256 /* my_realloc() ; Return old ptr on error */ #define MY_THREADSAFE 128 /* pread/pwrite: Don't allow interrupts */ +#define MY_DONT_OVERWRITE_FILE 1024 /* my_copy; Don't overwrite file */ #define MY_CHECK_ERROR 1 /* Params to my_end; Check open-close */ #define MY_GIVE_INFO 2 /* Give time info about process*/ diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 8b1c8ff1b44..e6a52ba8756 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -604,7 +604,7 @@ start_slave() $EXTRA_SLAVE_OPT $EXTRA_SLAVE_MYSQLD_OPT" if [ x$DO_DDD = x1 ] then - $ECHO "set args $master_args" > $GDB_SLAVE_INIT + $ECHO "set args $slave_args" > $GDB_SLAVE_INIT ddd --debugger "gdb -x $GDB_SLAVE_INIT" $SLAVE_MYSQLD & prompt_user "Hit enter to continue after you've started the slave" elif [ x$DO_GDB = x1 ] @@ -746,7 +746,7 @@ run_testcase () stop_master start_master else - if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] ; + if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] || [ -f $master_init_script ] then EXTRA_MASTER_OPT="" stop_master diff --git a/mysql-test/r/backup.result b/mysql-test/r/backup.result index 2bbe15954dc..0d34cd7eae8 100644 --- a/mysql-test/r/backup.result +++ b/mysql-test/r/backup.result @@ -1,10 +1,13 @@ Table Op Msg_type Msg_text -test.t1 backup error Failed copying .frm file: errno = X -test.t1 backup status Operation failed +test.t4 backup error Failed copying .frm file (errno: X) +test.t4 backup status Operation failed Table Op Msg_type Msg_text -test.t1 backup status OK +test.t4 backup status OK Table Op Msg_type Msg_text -test.t1 restore status OK +test.t4 backup error Failed copying .frm file (errno: X) +test.t4 backup status Operation failed +Table Op Msg_type Msg_text +test.t4 restore status OK count(*) 0 Table Op Msg_type Msg_text @@ -18,7 +21,6 @@ n 45 67 Table Op Msg_type Msg_text -test.t1 backup status OK test.t2 backup status OK test.t3 backup status OK Table Op Msg_type Msg_text @@ -40,4 +42,4 @@ k Table Op Msg_type Msg_text test.t1 restore status OK Table Op Msg_type Msg_text -test.t1 backup status OK +test.t5 backup status OK diff --git a/mysql-test/t/backup-master.sh b/mysql-test/t/backup-master.sh new file mode 100755 index 00000000000..99da5857afe --- /dev/null +++ b/mysql-test/t/backup-master.sh @@ -0,0 +1,5 @@ +#!/bin/sh +if [ "$MYSQL_TEST_DIR" ] +then + rm -f $MYSQL_TEST_DIR/var/tmp/*.frm $MYSQL_TEST_DIR/var/tmp/*.MY? +fi diff --git a/mysql-test/t/backup.test b/mysql-test/t/backup.test index 71343783d69..e4d5be00445 100644 --- a/mysql-test/t/backup.test +++ b/mysql-test/t/backup.test @@ -1,15 +1,23 @@ +# +# This test is a bit tricky as we can't use backup table to overwrite an old +# table +# connect (con1,localhost,root,,); connect (con2,localhost,root,,); connection con1; set SQL_LOG_BIN=0; -drop table if exists t1; +drop table if exists t1,t2,t3,t4; +create table t4(n int); +--replace_result "errno: 2" "errno: X" "errno: 22" "errno: X" "errno: 23" "errno: X" +backup table t4 to '../bogus'; +backup table t4 to '../tmp'; +--replace_result "errno: 17" "errno: X" +backup table t4 to '../tmp'; +drop table t4; +restore table t4 from '../tmp'; +select count(*) from t4; + create table t1(n int); ---replace_result "errno = 2" "errno = X" "errno = 22" "errno = X" "errno = 23" "errno = X" -backup table t1 to '../bogus'; -backup table t1 to '../tmp'; -drop table t1; -restore table t1 from '../tmp'; -select count(*) from t1; insert into t1 values (23),(45),(67); backup table t1 to '../tmp'; drop table t1; @@ -20,29 +28,24 @@ create table t2(m int not null primary key); create table t3(k int not null primary key); insert into t2 values (123),(145),(167); insert into t3 values (223),(245),(267); -backup table t1,t2,t3 to '../tmp'; +backup table t2,t3 to '../tmp'; drop table t1,t2,t3; restore table t1,t2,t3 from '../tmp'; select n from t1; select m from t2; select k from t3; -drop table t1,t2,t3; +drop table t1,t2,t3,t4; restore table t1 from '../tmp'; connection con2; +rename table t1 to t5; --send -lock tables t1 write; +lock tables t5 write; connection con1; --send -backup table t1 to '../tmp'; +backup table t5 to '../tmp'; connection con2; reap; unlock tables; connection con1; reap; -drop table t1; - - - - - - +drop table t5; diff --git a/mysys/my_copy.c b/mysys/my_copy.c index 9b02d84d063..5bc4d1d51fa 100644 --- a/mysys/my_copy.c +++ b/mysys/my_copy.c @@ -32,17 +32,29 @@ struct utimbuf { #endif - /* - Ordinary ownership and accesstimes are copied from 'from-file' - if MyFlags & MY_HOLD_ORIGINAL_MODES is set and to-file exists then - the modes of to-file isn't changed - Dont set MY_FNABP or MY_NABP bits on when calling this function ! - */ +/* + int my_copy(const char *from, const char *to, myf MyFlags) + + NOTES + Ordinary ownership and accesstimes are copied from 'from-file' + If MyFlags & MY_HOLD_ORIGINAL_MODES is set and to-file exists then + the modes of to-file isn't changed + If MyFlags & MY_DONT_OVERWRITE_FILE is set, we will give an error + if the file existed. + + WARNING + Don't set MY_FNABP or MY_NABP bits on when calling this function ! + + RETURN + 0 ok + # Error + +*/ int my_copy(const char *from, const char *to, myf MyFlags) { uint Count; - int new_file_stat; + int new_file_stat, create_flag; File from_file,to_file; char buff[IO_SIZE]; struct stat stat_buff,new_stat_buff; @@ -63,8 +75,10 @@ int my_copy(const char *from, const char *to, myf MyFlags) } if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat) stat_buff=new_stat_buff; + create_flag= (MyFlags & MY_DONT_OVERWRITE_FILE) ? O_EXCL : O_TRUNC; + if ((to_file= my_create(to,(int) stat_buff.st_mode, - O_WRONLY | O_TRUNC | O_BINARY | O_SHARE, + O_WRONLY | create_flag | O_BINARY | O_SHARE, MyFlags)) < 0) goto err; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 31a8d3c7109..1349e28b546 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -419,38 +419,38 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt) const char* errmsg = ""; if (!fn_format(dst_path, table_name, backup_dir, reg_ext, 4 + 64)) - { - errmsg = "Failed in fn_format() for .frm file: errno = %d"; - error = HA_ADMIN_INVALID; - goto err; - } + { + errmsg = "Failed in fn_format() for .frm file (errno: %d)"; + error = HA_ADMIN_INVALID; + goto err; + } if (my_copy(fn_format(src_path, table->path,"", reg_ext, 4), - dst_path, - MYF(MY_WME | MY_HOLD_ORIGINAL_MODES ))) + dst_path, + MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_DONT_OVERWRITE_FILE))) { error = HA_ADMIN_FAILED; - errmsg = "Failed copying .frm file: errno = %d"; + errmsg = "Failed copying .frm file (errno: %d)"; goto err; } if (!fn_format(dst_path, table_name, backup_dir, MI_NAME_DEXT, 4 + 64)) - { - errmsg = "Failed in fn_format() for .MYD file: errno = %d"; - error = HA_ADMIN_INVALID; - goto err; - } + { + errmsg = "Failed in fn_format() for .MYD file (errno: %d)"; + error = HA_ADMIN_INVALID; + goto err; + } if (my_copy(fn_format(src_path, table->path,"", MI_NAME_DEXT, 4), dst_path, - MYF(MY_WME | MY_HOLD_ORIGINAL_MODES )) ) - { - errmsg = "Failed copying .MYD file: errno = %d"; - error= HA_ADMIN_FAILED; - goto err; - } + MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_DONT_OVERWRITE_FILE))) + { + errmsg = "Failed copying .MYD file (errno: %d)"; + error= HA_ADMIN_FAILED; + goto err; + } return HA_ADMIN_OK; - err: +err: { MI_CHECK param; myisamchk_init(¶m); @@ -459,7 +459,7 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt) param.db_name = table->table_cache_key; param.table_name = table->table_name; param.testflag = 0; - mi_check_print_error(¶m,errmsg, errno ); + mi_check_print_error(¶m, errmsg, my_errno); return error; } } diff --git a/sql/slave.cc b/sql/slave.cc index a1972dc5a5d..358a908e0cc 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1270,6 +1270,17 @@ This may also be a network problem, or just a bug in the master or slave code.\ pthread_handler_decl(handle_slave,arg __attribute__((unused))) { + // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff + my_thread_init(); + if (!server_id) + { + pthread_cond_broadcast(&COND_slave_start); + sql_print_error("Server id not set, will not start slave"); + my_thread_end(); + pthread_exit((void*)1); + } + DBUG_ENTER("handle_slave"); + #ifndef DBUG_OFF slave_begin: #endif @@ -1278,20 +1289,14 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused))) char llbuff[22]; pthread_mutex_lock(&LOCK_slave); - if (!server_id) + + if (slave_running) { pthread_cond_broadcast(&COND_slave_start); pthread_mutex_unlock(&LOCK_slave); - sql_print_error("Server id not set, will not start slave"); - pthread_exit((void*)1); + my_thread_end(); + pthread_exit((void*)1); // safety just in case } - - if(slave_running) - { - pthread_cond_broadcast(&COND_slave_start); - pthread_mutex_unlock(&LOCK_slave); - pthread_exit((void*)1); // safety just in case - } slave_running = 1; abort_slave = 0; #ifndef DBUG_OFF @@ -1304,11 +1309,8 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused))) bool retried_once = 0; ulonglong last_failed_pos = 0; - // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff - my_thread_init(); slave_thd = thd = new THD; // note that contructor of THD uses DBUG_ ! thd->set_time(); - DBUG_ENTER("handle_slave"); pthread_detach_this_thread(); if (init_slave_thread(thd) || init_master_info(&glob_mi)) @@ -1518,18 +1520,18 @@ position %s", abort_slave = 0; save_temporary_tables = thd->temporary_tables; thd->temporary_tables = 0; // remove tempation from destructor to close them - pthread_cond_broadcast(&COND_slave_stopped); // tell the world we are done - pthread_mutex_unlock(&LOCK_slave); net_end(&thd->net); // destructor will not free it, because we are weird slave_thd = 0; (void) pthread_mutex_lock(&LOCK_thread_count); delete thd; (void) pthread_mutex_unlock(&LOCK_thread_count); - my_thread_end(); + pthread_mutex_unlock(&LOCK_slave); + pthread_cond_broadcast(&COND_slave_stopped); // tell the world we are done #ifndef DBUG_OFF if(abort_slave_event_count && !events_till_abort) goto slave_begin; #endif + my_thread_end(); pthread_exit(0); DBUG_RETURN(0); // Can't return anything here } |