diff options
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 |
commit | 2ad690fdf8a1141be8439a7e2d53974a0d3ec923 (patch) | |
tree | 49835843b47b50726e5c3eb2fde225851827a677 /sql/sql_lex.cc | |
parent | f860873c0d1a16b85388f7d02c5bd2d201087513 (diff) | |
download | mariadb-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.cc | 19 |
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. */ } } |