diff options
author | <anders.song@greatopensource.com> | 2011-01-15 13:48:16 +0800 |
---|---|---|
committer | <anders.song@greatopensource.com> | 2011-01-15 13:48:16 +0800 |
commit | ade1c74b3f9b662a572b843b7090fc68c5777ca9 (patch) | |
tree | 47cd4d625ae5d451bf005ef0bcb792887b74d631 /sql/sql_lex.cc | |
parent | 0355456dfbe077f55981bf03b9a1ce3c1622d3df (diff) | |
download | mariadb-git-ade1c74b3f9b662a572b843b7090fc68c5777ca9.tar.gz |
BUG#49124 Security issue with /*!-versioned */ SQL statements on Slave
Backport to 5.0.
/*![: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 | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 17ee53d446b..a013d5466c1 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -109,7 +109,7 @@ st_parsing_options::reset() } Lex_input_stream::Lex_input_stream(THD *thd, - const char* buffer, + char* buffer, unsigned int length) : m_thd(thd), yylineno(1), @@ -580,7 +580,7 @@ int MYSQLlex(void *arg, void *yythd) state=MY_LEX_COMMENT; break; } - yylval->lex_str.str=(char*) (lip->ptr=lip->tok_start);// Set to first chr + yylval->lex_str.str=lip->ptr=(char*)lip->tok_start;// Set to first chr yylval->lex_str.length=1; c=yyGet(); if (c != ')') @@ -946,6 +946,9 @@ int MYSQLlex(void *arg, void *yythd) state = MY_LEX_START; // Try again break; case MY_LEX_LONG_COMMENT: /* Long C comment? */ + { + char *version_mark= NULL; + if (yyPeek() != '*') { state=MY_LEX_CHAR; // Probable division @@ -956,6 +959,8 @@ int MYSQLlex(void *arg, void *yythd) if (yyPeek() == '!') // MySQL command in comment { ulong version=MYSQL_VERSION_ID; + version_mark= lip->ptr; + yySkip(); state=MY_LEX_START; if (my_isdigit(cs,yyPeek())) @@ -964,9 +969,18 @@ int MYSQLlex(void *arg, void *yythd) } if (version <= MYSQL_VERSION_ID) { - lex->in_comment=1; + lex->in_comment=1; + version_mark= NULL; break; } + else + { + /* + Patch and skip the conditional comment to avoid it + being propagated infinitely (eg. to a slave). + */ + *version_mark= ' '; + } } /* Discard: @@ -995,8 +1009,13 @@ int MYSQLlex(void *arg, void *yythd) } /* Unbalanced comments with a missing '*' '/' are a syntax error */ if (! comment_closed) + { + if (version_mark != NULL) + *version_mark= '!'; return (ABORT_SYM); + } break; + } case MY_LEX_END_LONG_COMMENT: if (lex->in_comment && yyPeek() == '/') { |