]> git.pld-linux.org Git - packages/mysql.git/blobdiff - show_slave_status_nolock.patch
- added patch for CVE-2012-2122
[packages/mysql.git] / show_slave_status_nolock.patch
index 9c76d118033c30a62dc59c91423f9532b7959be5..32dcd7fe50f73194f030cc2f186f13949ad7f544 100644 (file)
@@ -5,9 +5,8 @@
 #!!! notice !!!
 # Any small change to this file in the main branch
 # should be done or reviewed by the maintainer!
-diff -ruN a/patch_info/show_slave_status_nolock.patch b/patch_info/show_slave_status_nolock.patch
---- a/patch_info/show_slave_status_nolock.patch        1970-01-01 03:00:00.000000000 +0300
-+++ b/patch_info/show_slave_status_nolock.patch        2010-12-29 20:38:13.000000000 +0300
+--- /dev/null
++++ b/patch_info/show_slave_status_nolock.patch
 @@ -0,0 +1,6 @@
 +File=show_slave_status_nolock.patch
 +Name= SHOW SLAVE STATUS NOLOCK
@@ -15,9 +14,8 @@ diff -ruN a/patch_info/show_slave_status_nolock.patch b/patch_info/show_slave_st
 +Author=Percona <info@percona.com>
 +License=GPL
 +Comment= Implement SHOW SLAVE STATUS without lock (STOP SLAVE lock the same mutex what lock SHOW SLAVE STATUS)
-diff -ruN a/sql/lex.h b/sql/lex.h
---- a/sql/lex.h        2010-12-29 20:27:19.000000000 +0300
-+++ b/sql/lex.h        2010-12-29 20:28:57.000000000 +0300
+--- a/sql/lex.h
++++ b/sql/lex.h
 @@ -378,6 +378,7 @@
    { "NONE",           SYM(NONE_SYM)},
    { "NOT",            SYM(NOT_SYM)},
@@ -26,10 +24,9 @@ diff -ruN a/sql/lex.h b/sql/lex.h
    { "NULL",           SYM(NULL_SYM)},
    { "NUMERIC",                SYM(NUMERIC_SYM)},
    { "NVARCHAR",               SYM(NVARCHAR_SYM)},
-diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
---- a/sql/mysqld.cc    2010-12-29 20:27:19.000000000 +0300
-+++ b/sql/mysqld.cc    2010-12-29 20:29:19.000000000 +0300
-@@ -3067,6 +3067,7 @@
+--- a/sql/mysqld.cc
++++ b/sql/mysqld.cc
+@@ -2971,6 +2971,7 @@
    {"show_relaylog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_RELAYLOG_EVENTS]), SHOW_LONG_STATUS},
    {"show_slave_hosts",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS},
    {"show_slave_status",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS},
@@ -37,9 +34,8 @@ diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
    {"show_status",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
    {"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS},
    {"show_table_status",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS},
-diff -ruN a/sql/sql_lex.h b/sql/sql_lex.h
---- a/sql/sql_lex.h    2010-12-29 20:27:19.000000000 +0300
-+++ b/sql/sql_lex.h    2010-12-29 20:32:26.000000000 +0300
+--- a/sql/sql_lex.h
++++ b/sql/sql_lex.h
 @@ -190,6 +190,8 @@
    SQLCOM_SHOW_PROFILE, SQLCOM_SHOW_PROFILES,
    SQLCOM_SIGNAL, SQLCOM_RESIGNAL,
@@ -49,9 +45,8 @@ diff -ruN a/sql/sql_lex.h b/sql/sql_lex.h
    /*
      When a command is added here, be sure it's also added in mysqld.cc
      in "struct show_var_st status_vars[]= {" ...
-diff -ruN a/sql/sql_parse.cc b/sql/sql_parse.cc
---- a/sql/sql_parse.cc 2010-12-29 20:27:19.000000000 +0300
-+++ b/sql/sql_parse.cc 2010-12-29 20:34:50.000000000 +0300
+--- a/sql/sql_parse.cc
++++ b/sql/sql_parse.cc
 @@ -336,6 +336,7 @@
    sql_command_flags[SQLCOM_SHOW_CREATE]=  CF_STATUS_COMMAND;
    sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND;
@@ -60,7 +55,7 @@ diff -ruN a/sql/sql_parse.cc b/sql/sql_parse.cc
    sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND;
    sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]= CF_STATUS_COMMAND;
    sql_command_flags[SQLCOM_SHOW_CREATE_TRIGGER]=  CF_STATUS_COMMAND;
-@@ -2269,12 +2270,16 @@
+@@ -2393,12 +2394,17 @@
      mysql_mutex_unlock(&LOCK_active_mi);
      break;
    }
@@ -71,29 +66,38 @@ diff -ruN a/sql/sql_parse.cc b/sql/sql_parse.cc
      if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
        goto error;
 -    mysql_mutex_lock(&LOCK_active_mi);
-+    if(SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command)
++    bool do_lock=SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command;
++    if(do_lock)
 +    {
 +      mysql_mutex_lock(&LOCK_active_mi);
 +    }
      if (active_mi != NULL)
      {
        res = show_master_info(thd, active_mi);
-@@ -2285,7 +2290,10 @@
+@@ -2409,7 +2415,19 @@
                     WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO));
        my_ok(thd);
      }
 -    mysql_mutex_unlock(&LOCK_active_mi);
-+    if(SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command)
++    if(do_lock)
 +    {
 +      mysql_mutex_unlock(&LOCK_active_mi);
 +    }
++    DBUG_EXECUTE_IF("after_show_slave_status",
++                    {
++                      const char act[]=
++                        "now "
++                        "signal signal.after_show_slave_status";
++                      DBUG_ASSERT(opt_debug_sync_timeout > 0);
++                      DBUG_ASSERT(!debug_sync_set_action(current_thd,
++                                                         STRING_WITH_LEN(act)));
++                    };);
      break;
    }
    case SQLCOM_SHOW_MASTER_STAT:
-diff -ruN a/sql/sql_yacc.yy b/sql/sql_yacc.yy
---- a/sql/sql_yacc.yy  2010-12-29 20:27:19.000000000 +0300
-+++ b/sql/sql_yacc.yy  2010-12-29 20:36:40.000000000 +0300
-@@ -1292,6 +1292,7 @@
+--- a/sql/sql_yacc.yy
++++ b/sql/sql_yacc.yy
+@@ -1293,6 +1293,7 @@
  %token  STARTS_SYM
  %token  START_SYM                     /* SQL-2003-R */
  %token  STATUS_SYM
@@ -101,10 +105,11 @@ diff -ruN a/sql/sql_yacc.yy b/sql/sql_yacc.yy
  %token  STDDEV_SAMP_SYM               /* SQL-2003-N */
  %token  STD_SYM
  %token  STOP_SYM
-@@ -11095,6 +11096,10 @@
+@@ -11111,6 +11112,11 @@
            {
              Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
            }
++      /* SHOW SLAVE STATUS NOLOCK */
 +        | SLAVE STATUS_SYM NOLOCK_SYM
 +          {
 +          Lex->sql_command = SQLCOM_SHOW_SLAVE_NOLOCK_STAT; //SQLCOM_SHOW_SLAVE_NOLOCK_STAT;
@@ -112,3 +117,255 @@ diff -ruN a/sql/sql_yacc.yy b/sql/sql_yacc.yy
          | QUERY_RESPONSE_TIME_SYM wild_and_where
           {
  #ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
+--- /dev/null
++++ b/mysql-test/t/percona_show_slave_status_nolock.test
+@@ -0,0 +1,90 @@
++--source include/master-slave.inc
++--source include/have_debug_sync.inc
++--source include/have_binlog_format_statement.inc
++
++call mtr.add_suppression("Slave SQL: Request to stop slave SQL Thread received while applying a group that has non-transactional changes");
++
++--let $rpl_connection_name=slave_lock
++--let $rpl_server_number=2
++--source include/rpl_connect.inc
++
++--let $rpl_connection_name=slave_nolock
++--let $rpl_server_number=2
++--source include/rpl_connect.inc
++
++--let $show_statement= SHOW PROCESSLIST
++--let $field= Info
++
++connection master;
++--echo [master]
++--disable_warnings
++DROP TABLE IF EXISTS t;
++--enable_warnings
++CREATE TABLE t(id INT);
++sync_slave_with_master;
++
++connection slave;
++--echo [slave]
++SET DEBUG_SYNC='RESET';
++SET GLOBAL DEBUG="+d,after_mysql_insert,after_show_slave_status";
++
++connection master;
++--echo [master]
++INSERT INTO t VALUES(0);
++
++connection slave;
++--echo [slave]
++--let $condition= 'INSERT INTO t VALUES(0)'
++--source include/wait_show_condition.inc
++
++--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine
++--source include/percona_show_slave_status_nolock.inc
++
++connection master;
++--echo [master]
++INSERT INTO t VALUES(1);
++
++connection slave;
++--echo [slave]
++--let $condition= 'INSERT INTO t VALUES(1)'
++--source include/wait_show_condition.inc
++
++--let $rpl_connection_name=slave_stop
++--let $rpl_server_number=2
++--source include/rpl_connect.inc
++
++connection slave_stop;
++--echo [slave_stop]
++send STOP SLAVE;
++
++connection slave;
++--echo [slave]
++--let $condition= 'STOP SLAVE'
++--source include/wait_show_condition.inc
++
++--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine
++--source include/percona_show_slave_status_nolock.inc
++
++
++connection slave_stop;
++--echo [slave_stop]
++reap;
++--source include/wait_for_slave_to_stop.inc
++START SLAVE;
++--source include/wait_for_slave_to_start.inc
++
++connection master;
++--echo [master]
++SET DEBUG_SYNC='RESET';
++
++connection slave;
++--echo [slave]
++SET GLOBAL DEBUG='';
++SET DEBUG_SYNC='RESET';
++
++connection master;
++--echo [master]
++DROP TABLE t;
++sync_slave_with_master;
++
++--source include/rpl_end.inc
+--- /dev/null
++++ b/mysql-test/r/percona_show_slave_status_nolock.result
+@@ -0,0 +1,69 @@
++include/master-slave.inc
++[connection master]
++call mtr.add_suppression("Slave SQL: Request to stop slave SQL Thread received while applying a group that has non-transactional changes");
++include/rpl_connect.inc [creating slave_lock]
++include/rpl_connect.inc [creating slave_nolock]
++[master]
++DROP TABLE IF EXISTS t;
++CREATE TABLE t(id INT);
++[slave]
++SET DEBUG_SYNC='RESET';
++SET GLOBAL DEBUG="+d,after_mysql_insert,after_show_slave_status";
++[master]
++INSERT INTO t VALUES(0);
++[slave]
++check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine
++
++[slave_lock]
++SHOW SLAVE STATUS;
++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
++SIGNAL after SHOW SLAVE STATUS is 'signal.after_show_slave_status'
++[slave]
++SET DEBUG_SYNC='now SIGNAL signal.empty';
++[slave_nolock]
++SHOW SLAVE STATUS NOLOCK;
++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
++# should be 'signal.after_show_slave_status'
++SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status'
++[slave]
++SET DEBUG_SYNC='now SIGNAL signal.continue';
++[slave]
++SET DEBUG_SYNC='now SIGNAL signal.empty';
++
++[master]
++INSERT INTO t VALUES(1);
++[slave]
++include/rpl_connect.inc [creating slave_stop]
++[slave_stop]
++STOP SLAVE;
++[slave]
++check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine
++
++[slave_lock]
++SHOW SLAVE STATUS;
++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
++SIGNAL after SHOW SLAVE STATUS is 'signal.empty'
++[slave]
++SET DEBUG_SYNC='now SIGNAL signal.empty';
++[slave_nolock]
++SHOW SLAVE STATUS NOLOCK;
++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
++# should be 'signal.after_show_slave_status'
++SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status'
++[slave]
++SET DEBUG_SYNC='now SIGNAL signal.continue';
++[slave]
++SET DEBUG_SYNC='now SIGNAL signal.empty';
++
++[slave_stop]
++include/wait_for_slave_to_stop.inc
++START SLAVE;
++include/wait_for_slave_to_start.inc
++[master]
++SET DEBUG_SYNC='RESET';
++[slave]
++SET GLOBAL DEBUG='';
++SET DEBUG_SYNC='RESET';
++[master]
++DROP TABLE t;
++include/rpl_end.inc
+--- /dev/null
++++ b/mysql-test/include/percona_show_slave_status_nolock.inc
+@@ -0,0 +1,56 @@
++--echo
++--disable_result_log
++connection slave_lock;
++--echo [slave_lock]
++send SHOW SLAVE STATUS;
++
++connection slave;
++--let $condition= 'SHOW SLAVE STATUS'
++--source include/wait_show_condition.inc
++
++--disable_warnings
++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
++--enable_warnings
++
++--let current=`SELECT SUBSTR(Variable_value FROM 22) FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name = 'DEBUG_SYNC'`
++--echo SIGNAL after SHOW SLAVE STATUS is $current
++
++connection slave;
++--echo [slave]
++SET DEBUG_SYNC='now SIGNAL signal.empty';
++
++connection slave_nolock;
++--echo [slave_nolock]
++send SHOW SLAVE STATUS NOLOCK;
++
++connection slave;
++--let $condition= 'SHOW SLAVE STATUS NOLOCK'
++--source include/wait_show_condition.inc
++
++--disable_warnings
++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
++--enable_warnings
++
++--echo # should be 'signal.after_show_slave_status'
++--let current=`SELECT SUBSTR(Variable_value FROM 22) FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name = 'DEBUG_SYNC'`
++--echo SIGNAL after SHOW SLAVE STATUS NOLOCK is $current
++
++connection slave;
++--echo [slave]
++SET DEBUG_SYNC='now SIGNAL signal.continue';
++
++connection slave_lock;
++--disable_result_log
++reap;
++--enable_result_log
++
++connection slave_nolock;
++--disable_result_log
++reap;
++--enable_result_log
++
++connection slave;
++--echo [slave]
++SET DEBUG_SYNC='now SIGNAL signal.empty';
++--enable_result_log
++--echo
+--- a/sql/slave.cc
++++ b/sql/slave.cc
+@@ -1816,6 +1816,7 @@
+   if (mi->host[0])
+   {
++    bool do_lock=SQLCOM_SHOW_SLAVE_NOLOCK_STAT != thd->lex->sql_command;
+     DBUG_PRINT("info",("host is set: '%s'", mi->host));
+     String *packet= &thd->packet;
+     protocol->prepare_for_resend();
+@@ -1824,9 +1825,15 @@
+       slave_running can be accessed without run_lock but not other
+       non-volotile members like mi->io_thd, which is guarded by the mutex.
+     */
+-    mysql_mutex_lock(&mi->run_lock);
++    if (do_lock)
++    {
++      mysql_mutex_lock(&mi->run_lock);
++    }
+     protocol->store(mi->io_thd ? mi->io_thd->proc_info : "", &my_charset_bin);
+-    mysql_mutex_unlock(&mi->run_lock);
++    if (do_lock)
++    {
++      mysql_mutex_unlock(&mi->run_lock);
++    }
+     mysql_mutex_lock(&mi->data_lock);
+     mysql_mutex_lock(&mi->rli.data_lock);
This page took 0.046916 seconds and 4 git commands to generate.