summaryrefslogtreecommitdiff
path: root/sql/sql_lex.cc
diff options
context:
space:
mode:
author <Li-Bing.Song@sun.com>2010-07-29 11:00:57 +0800
committer <Li-Bing.Song@sun.com>2010-07-29 11:00:57 +0800
commit2ad690fdf8a1141be8439a7e2d53974a0d3ec923 (patch)
tree49835843b47b50726e5c3eb2fde225851827a677 /sql/sql_lex.cc
parentf860873c0d1a16b85388f7d02c5bd2d201087513 (diff)
downloadmariadb-git-2ad690fdf8a1141be8439a7e2d53974a0d3ec923.tar.gz
BUG#49124 Security issue with /*!-versioned */ SQL statements on Slave
/*![:version:] Query Code */, where [:version:] is a sequence of 5 digits representing the mysql server version(e.g /*!50200 ... */), 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: - To replace '!' with ' ' 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)*/
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r--sql/sql_lex.cc19
1 files changed, 15 insertions, 4 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 6bfd6f3906c..2bff036b1f1 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -111,7 +111,7 @@ st_parsing_options::reset()
}
-bool Lex_input_stream::init(THD *thd, const char *buff, unsigned int length)
+bool Lex_input_stream::init(THD *thd, char *buff, unsigned int length)
{
DBUG_EXECUTE_IF("bug42064_simulate_oom",
DBUG_SET("+d,simulate_out_of_memory"););
@@ -1292,11 +1292,10 @@ int MYSQLlex(void *arg, void *yythd)
ulong version;
version=strtol(version_str, NULL, 10);
- /* Accept 'M' 'm' 'm' 'd' 'd' */
- lip->yySkipn(5);
-
if (version <= MYSQL_VERSION_ID)
{
+ /* Accept 'M' 'm' 'm' 'd' 'd' */
+ lip->yySkipn(5);
/* Expand the content of the special comment as real code */
lip->set_echo(TRUE);
state=MY_LEX_START;
@@ -1304,7 +1303,19 @@ int MYSQLlex(void *arg, void *yythd)
}
else
{
+ const char* version_mark= lip->get_ptr() - 1;
+ DBUG_ASSERT(*version_mark == '!');
+ /*
+ Patch and skip the conditional comment to avoid it
+ being propagated infinitely (eg. to a slave).
+ */
+ char *pcom= lip->yyUnput(' ');
comment_closed= ! consume_comment(lip, 1);
+ if (! comment_closed)
+ {
+ DBUG_ASSERT(pcom == version_mark);
+ *pcom= '!';
+ }
/* version allowed to have one level of comment inside. */
}
}