#At file:///home/anders/work/bzrwork1/wt1/mysql-5.1-bugteam/ based on revid:sergey.glukhov@stripped
3438 Li-Bing.Song@stripped 2010-06-24
BUG#49124 Security issue with /*!-versioned */ SQL statements on Slave
/*!50200 Query Code */ is a special comment that the query in it can
be executed on those servers whose versions are larger than the
version appearing in the comment. It leads to a security issue when
slave's version is larger than master's. A malicious user can improve
his privileges on slaves. Because slave SQL thread is running with
SUPER privileges, so it can execute queries that he/she does not have
privileges on master.
This bug is fixed with the logic below:
- Use '#' instead of '!' in the magic comments which are not applied on
master. So they become common comments and will not be applied on slave.
- Example:
'INSERT INTO t1 VALUES (1) /*!10000, (2)*/ /*!99999 ,(3)*/
will be binlogged as
'INSERT INTO t1 VALUES (1) /*!10000, (2)*/ /*#99999 ,(3)*/
added:
mysql-test/suite/rpl/r/rpl_magic_comments.result
mysql-test/suite/rpl/t/rpl_magic_comments.test
modified:
sql/sql_lex.cc
sql/sql_lex.h
=== added file 'mysql-test/suite/rpl/r/rpl_magic_comments.result'
--- a/mysql-test/suite/rpl/r/rpl_magic_comments.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_magic_comments.result 2010-06-24 10:18:04 +0000
@@ -0,0 +1,50 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+CREATE TABLE t1(c1 INT);
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; CREATE TABLE t1(c1 INT)
+
+# Case 1:
+# ------------------------------------------------------------------
+# In a statement, some MCs are applied while others are not. The Mcs
+# which are not applied on master will be binlogged as common comments.
+/*!99999 --- */INSERT /*!INTO*/ /*!10000 t1 */ VALUES(10) /*!99999 ,(11)*/;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; /*#99999 --- */INSERT /*!INTO*/ /*!10000 t1 */ VALUES(10) /*#99999 ,(11)*/
+Comparing tables master:test.t1 and slave:test.t1
+
+# Case 2:
+# -----------------------------------------------------------------
+# Verify whether it can be binlogged correctly when executing prepared
+# statement.
+PREPARE stmt FROM 'INSERT INTO /*!99999 blabla*/ t1 VALUES(60) /*!99999 ,(61)*/';
+EXECUTE stmt;
+DROP TABLE t1;
+CREATE TABLE t1(c1 INT);
+EXECUTE stmt;
+Comparing tables master:test.t1 and slave:test.t1
+
+SET @value=62;
+PREPARE stmt FROM 'INSERT INTO /*!99999 blabla */ t1 VALUES(?) /*!99999 ,(63)*/';
+EXECUTE stmt USING @value;
+DROP TABLE t1;
+CREATE TABLE t1(c1 INT);
+EXECUTE stmt USING @value;
+show binlog events from <binlog_start>;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Query # # use `test`; INSERT INTO /*#99999 blabla*/ t1 VALUES(60) /*#99999 ,(61)*/
+master-bin.000001 # Query # # use `test`; DROP TABLE t1
+master-bin.000001 # Query # # use `test`; CREATE TABLE t1(c1 INT)
+master-bin.000001 # Query # # use `test`; INSERT INTO /*#99999 blabla*/ t1 VALUES(60) /*#99999 ,(61)*/
+master-bin.000001 # Query # # use `test`; INSERT INTO /*#99999 blabla */ t1 VALUES(62) /*#99999 ,(63)*/
+master-bin.000001 # Query # # use `test`; DROP TABLE t1
+master-bin.000001 # Query # # use `test`; CREATE TABLE t1(c1 INT)
+master-bin.000001 # Query # # use `test`; INSERT INTO /*#99999 blabla */ t1 VALUES(62) /*#99999 ,(63)*/
+Comparing tables master:test.t1 and slave:test.t1
+DROP TABLE t1;
=== added file 'mysql-test/suite/rpl/t/rpl_magic_comments.test'
--- a/mysql-test/suite/rpl/t/rpl_magic_comments.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_magic_comments.test 2010-06-24 10:18:04 +0000
@@ -0,0 +1,67 @@
+###############################################################################
+# After the patch for BUG#49124:
+# - Use '#' instead of '!' in the magic comments which are not applied on
+# master. So they become common comments and will not be applied on slave.
+#
+# - Example:
+# 'INSERT INTO t1 VALUES (1) /*!10000, (2)*/ /*!99999 ,(3)*/ will be
+# binlogged as
+# 'INSERT INTO t1 VALUES (1) /*!10000, (2)*/ /*#99999 ,(3)*/'.
+###############################################################################
+source include/master-slave.inc;
+source include/have_binlog_format_statement.inc;
+
+CREATE TABLE t1(c1 INT);
+source include/show_binlog_events.inc;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+--echo
+--echo # Case 1:
+--echo # ------------------------------------------------------------------
+--echo # In a statement, some MCs are applied while others are not. The Mcs
+--echo # which are not applied on master will be binlogged as common comments.
+
+/*!99999 --- */INSERT /*!INTO*/ /*!10000 t1 */ VALUES(10) /*!99999 ,(11)*/;
+
+source include/show_binlog_events.inc;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+sync_slave_with_master;
+let $diff_table_1=master:test.t1;
+let $diff_table_2=slave:test.t1;
+source include/diff_tables.inc;
+
+--echo
+--echo # Case 2:
+--echo # -----------------------------------------------------------------
+--echo # Verify whether it can be binlogged correctly when executing prepared
+--echo # statement.
+PREPARE stmt FROM 'INSERT INTO /*!99999 blabla*/ t1 VALUES(60) /*!99999 ,(61)*/';
+EXECUTE stmt;
+DROP TABLE t1;
+CREATE TABLE t1(c1 INT);
+EXECUTE stmt;
+
+sync_slave_with_master;
+let $diff_table_1=master:test.t1;
+let $diff_table_2=slave:test.t1;
+source include/diff_tables.inc;
+
+--echo
+SET @value=62;
+PREPARE stmt FROM 'INSERT INTO /*!99999 blabla */ t1 VALUES(?) /*!99999 ,(63)*/';
+EXECUTE stmt USING @value;
+DROP TABLE t1;
+CREATE TABLE t1(c1 INT);
+EXECUTE stmt USING @value;
+
+source include/show_binlog_events.inc;
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+sync_slave_with_master;
+let $diff_table_1=master:test.t1;
+let $diff_table_2=slave:test.t1;
+source include/diff_tables.inc;
+
+DROP TABLE t1;
+sync_slave_with_master;
+source include/master-slave-end.inc;
=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc 2010-06-11 12:52:06 +0000
+++ b/sql/sql_lex.cc 2010-06-24 10:18:04 +0000
@@ -1304,6 +1304,7 @@ int MYSQLlex(void *arg, void *yythd)
}
else
{
+ lip->yySet(-6, '#');
comment_closed= ! consume_comment(lip, 1);
/* version allowed to have one level of comment inside. */
}
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2010-06-11 12:52:06 +0000
+++ b/sql/sql_lex.h 2010-06-24 10:18:04 +0000
@@ -1220,6 +1220,17 @@ public:
}
/**
+ Assign a character to a given position in the buf.
+ @param n the position related to m_ptr.
+ @param c the value which should be set into the buf.
+ */
+ void yySet(int n, char c)
+ {
+ char *ptr= (char *)m_ptr + n;
+ *ptr= c;
+ }
+
+ /**
Get a character, and advance in the stream.
@return the next character to parse.
*/
Attachment: [text/bzr-bundle] bzr/li-bing.song@sun.com-20100624101804-he6g9oivvehdfjue.bundle