Commit 689a96fc authored by Sven Sandberg's avatar Sven Sandberg

BUG#55322: SHOW BINLOG EVENTS increases @@SESSION.MAX_ALLOWED_PACKET

Problem: when SHOW BINLOG EVENTS was issued, it increased the value of
@@session.max_allowed_packet. This allowed a non-root user to increase
the amount of memory used by her thread arbitrarily. Thus, it removes
the bound on the amount of system resources used by a client, so it
presents a security risk (DoS attack).

Fix: it is correct to increase the value of @@session.max_allowed_packet
while executing SHOW BINLOG EVENTS (see BUG 30435). However, the
increase should only be temporary. Thus, the fix is to restore the value
when SHOW BINLOG EVENTS ends.
The value of @@session.max_allowed_packet is also increased in
mysql_binlog_send (i.e., the binlog dump thread). It is not clear if this
can cause any trouble, since normally the client that issues
COM_BINLOG_DUMP will not issue any other commands that would be affected
by the increased value of @@session.max_allowed_packet. However, we
restore the value just in case.


mysql-test/suite/rpl/r/rpl_packet.result:
  update result file
mysql-test/suite/rpl/t/rpl_packet.test:
  Add test that verifies that @@session.max_allowed_packet does not change
  when issuing SHOW BINLOG EVENTS.
  Make previous sub-test clean up.
  Add comments listing the bugs in this test case.
sql/sql_repl.cc:
  Restore the old value of thd->variables.max_allowed_packet at the
  end of mysql_binlog_send and mysql_show_binlog_events.
parent 05d1d687
...@@ -49,6 +49,14 @@ Slave_IO_Running = No (expect No) ...@@ -49,6 +49,14 @@ Slave_IO_Running = No (expect No)
SELECT "Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master'" AS Last_IO_Error; SELECT "Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master'" AS Last_IO_Error;
Last_IO_Error Last_IO_Error
Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master' Got fatal error 1236 from master when reading data from binary log: 'log event entry exceeded max_allowed_packet; Increase max_allowed_packet on master'
STOP SLAVE;
RESET SLAVE;
RESET MASTER;
SET @max_allowed_packet_0= @@session.max_allowed_packet;
SHOW BINLOG EVENTS;
SET @max_allowed_packet_1= @@session.max_allowed_packet;
SHOW BINLOG EVENTS;
SET @max_allowed_packet_2= @@session.max_allowed_packet;
==== clean up ==== ==== clean up ====
DROP TABLE t1; DROP TABLE t1;
SET @@global.max_allowed_packet= 1024; SET @@global.max_allowed_packet= 1024;
......
# ==== Purpose ====
# #
# Check replication protocol packet size handling # Check replication protocol packet size handling
# Bug#19402 SQL close to the size of the max_allowed_packet fails on slave
# #
# ==== Related bugs ====
# Bug#19402 SQL close to the size of the max_allowed_packet fails on slave
# BUG#23755: Replicated event larger that max_allowed_packet infinitely re-transmits
# BUG#42914: No LAST_IO_ERROR for max_allowed_packet errors
# BUG#55322: SHOW BINLOG EVENTS increases @@SESSION.MAX_ALLOWED_PACKET
# max-out size db name # max-out size db name
source include/master-slave.inc; source include/master-slave.inc;
...@@ -119,6 +124,38 @@ let $slave_io_running= query_get_value(SHOW SLAVE STATUS, Slave_IO_Running, 1); ...@@ -119,6 +124,38 @@ let $slave_io_running= query_get_value(SHOW SLAVE STATUS, Slave_IO_Running, 1);
let $last_io_error= query_get_value(SHOW SLAVE STATUS, Last_IO_Error, 1); let $last_io_error= query_get_value(SHOW SLAVE STATUS, Last_IO_Error, 1);
eval SELECT "$last_io_error" AS Last_IO_Error; eval SELECT "$last_io_error" AS Last_IO_Error;
# Remove the bad binlog and clear error status on slave.
STOP SLAVE;
RESET SLAVE;
--connection master
RESET MASTER;
#
# BUG#55322: SHOW BINLOG EVENTS increases @@SESSION.MAX_ALLOWED_PACKET
#
# In BUG#55322, @@session.max_allowed_packet increased each time SHOW
# BINLOG EVENTS was issued. To verify that this bug is fixed, we
# execute SHOW BINLOG EVENTS twice and check that max_allowed_packet
# never changes. We turn off the result log because we don't care
# about the contents of the binlog.
--disable_result_log
SET @max_allowed_packet_0= @@session.max_allowed_packet;
SHOW BINLOG EVENTS;
SET @max_allowed_packet_1= @@session.max_allowed_packet;
SHOW BINLOG EVENTS;
SET @max_allowed_packet_2= @@session.max_allowed_packet;
--enable_result_log
if (`SELECT NOT(@max_allowed_packet_0 = @max_allowed_packet_1 AND @max_allowed_packet_1 = @max_allowed_packet_2)`)
{
--echo ERROR: max_allowed_packet changed after executing SHOW BINLOG EVENTS
--source include/show_rpl_debug_info.inc
SELECT @max_allowed_packet_0, @max_allowed_packet_1, @max_allowed_packet_2;
--die @max_allowed_packet changed after executing SHOW BINLOG EVENTS
}
--echo ==== clean up ==== --echo ==== clean up ====
connection master; connection master;
DROP TABLE t1; DROP TABLE t1;
......
...@@ -357,6 +357,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ...@@ -357,6 +357,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
#ifndef DBUG_OFF #ifndef DBUG_OFF
int left_events = max_binlog_dump_events; int left_events = max_binlog_dump_events;
#endif #endif
int old_max_allowed_packet= thd->variables.max_allowed_packet;
DBUG_ENTER("mysql_binlog_send"); DBUG_ENTER("mysql_binlog_send");
DBUG_PRINT("enter",("log_ident: '%s' pos: %ld", log_ident, (long) pos)); DBUG_PRINT("enter",("log_ident: '%s' pos: %ld", log_ident, (long) pos));
...@@ -762,6 +763,7 @@ end: ...@@ -762,6 +763,7 @@ end:
pthread_mutex_lock(&LOCK_thread_count); pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0; thd->current_linfo = 0;
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
thd->variables.max_allowed_packet= old_max_allowed_packet;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
err: err:
...@@ -779,6 +781,7 @@ err: ...@@ -779,6 +781,7 @@ err:
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
if (file >= 0) if (file >= 0)
(void) my_close(file, MYF(MY_WME)); (void) my_close(file, MYF(MY_WME));
thd->variables.max_allowed_packet= old_max_allowed_packet;
my_message(my_errno, errmsg, MYF(0)); my_message(my_errno, errmsg, MYF(0));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -1422,6 +1425,7 @@ bool mysql_show_binlog_events(THD* thd) ...@@ -1422,6 +1425,7 @@ bool mysql_show_binlog_events(THD* thd)
bool ret = TRUE; bool ret = TRUE;
IO_CACHE log; IO_CACHE log;
File file = -1; File file = -1;
int old_max_allowed_packet= thd->variables.max_allowed_packet;
DBUG_ENTER("mysql_show_binlog_events"); DBUG_ENTER("mysql_show_binlog_events");
Log_event::init_show_field_list(&field_list); Log_event::init_show_field_list(&field_list);
...@@ -1560,6 +1564,7 @@ err: ...@@ -1560,6 +1564,7 @@ err:
pthread_mutex_lock(&LOCK_thread_count); pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0; thd->current_linfo = 0;
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
thd->variables.max_allowed_packet= old_max_allowed_packet;
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment