MDEV-8628 Expand current_user In binlog For GRANT/REVOKE/RENAME/DROPU…#5162
MDEV-8628 Expand current_user In binlog For GRANT/REVOKE/RENAME/DROPU…#5162LukeYL026 wants to merge 1 commit into
Conversation
|
|
There was a problem hiding this comment.
Code Review
This pull request addresses MDEV-8628 by expanding the literal CURRENT_USER keyword to the actual 'user'@'host' in the binlog for statements like GRANT, REVOKE, RENAME USER, DROP USER, and ALTER USER. The review feedback identifies two critical issues in the query rewriting logic: a potential out-of-bounds read when a backslash is at the end of a quoted string, and a recommendation to use the existing append_user helper to safely format the user and host strings while avoiding null pointer dereferences.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
57a9d62 to
147b001
Compare
…SER/ALTERUSER When GRANT, REVOKE, RENAME USER, DROP USER, or ALTER USER reference CURRENT_USER, the binlog stores the raw SQL with the literal keyword rather than the resolved 'user'@'host' value. Live replication works because the slave SQL thread reads Q_INVOKER metadata from the binary event to resolve CURRENT_USER correctly. However, when the binlog is replayed via mysqlbinlog | mysql, the metadata is lost and CURRENT_USER resolves to whoever runs the replay client, producing wrong results. Fix by replacing CURRENT_USER with the expanded 'user'@'host' in the SQL text before writing to the binlog. Unlike SET PASSWORD which has a rigid fixed format (SET PASSWORD FOR 'user'@'host' = 'hash') and can reconstruct the entire query via sprintf, statements like GRANT and REVOKE have variable syntax with CURRENT_USER appearing at arbitrary positions in multi-user lists, optional clauses, and different grant targets. A text replacement helper is needed to handle this without reconstructing the full query for each statement type. The helper scans the query string, skips quoted literals, and performs a case-insensitive replacement of standalone current_user (with optional parentheses). It is called at each affected write_bin_log() call site only when the statement's user list contains CURRENT_USER, adding zero overhead to the common case. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services, Inc.
147b001 to
9ca9b2e
Compare
Description
In MariaDB, non-deterministic DDL statements involving
CURRENT_USER()orCURRENT_USERare only expanded forSET PASSWORDwhen stored into the binlog event body as statement. Other commands likeGRANTremain non-deterministic, with unexpandedCURRENT_USER.While replication remains unaffected — the slave can resolve
CURRENT_USERusing metadata in event headers — binlog statements should still be deterministic. When the binlog is replayed viamysqlbinlog | mysql, only the raw SQL statement is returned and metadata is lost, leaving an unresolved, and hence non-deterministiccurrent_userin the statement.SET PASSWORDis already correct — it constructs a new query string viasprintfwith a rigid formatSET PASSWORD FOR 'user'@'host' = 'hash'. The remaining commands can haveCURRENT_USERappearing at arbitrary positions, making full query reconstruction impractical. String replacement is the pragmatic approach.This patch introduces
rewrite_query_expanding_current_user()insql/sql_acl.cc— a helper that performs a case-insensitive replacement of standalonecurrent_user(with optional parentheses) with the quoted'user'@'host'from the session's security context. The helper is invoked before each affectedwrite_bin_log()call site only when the statement's user list containsCURRENT_USER.Affected statements:
GRANTREVOKERENAME USERDROP USERALTER USERCREATE FUNCTIONCREATE PROCEDURECREATE TRIGGERCREATE EVENTCREATE VIEWALTER EVENTALTER VIEWRelease Notes
Binlog replay via
mysqlbinlog | mysqlnow correctly handles all listed statements that referenceCURRENT_USER. Previously these statements retained an unresolvablecurrent_userin raw SQL.How can this PR be tested?
New MTR test
binlog.binlog_mdev8628covers the following cases to confirm thatCURRENT_USERin the binlog event body is resolved to the actual'user'@'host'value:current_userwithout parenthesesCURRENT_USER()with parenthesescUrReNt_UsErALTER USERwithCURRENT_USERCURRENT_USERin a multi-userGRANTlistRENAME USERwithCURRENT_USERon both sidesREVOKE ALL PRIVILEGESwithCURRENT_USERGRANT/REVOKErole withCURRENT_USER(mysql_grant_rolepath)GRANT/REVOKEon a procedure withCURRENT_USER(mysql_routine_grantpath)SET PASSWORDwithCURRENT_USER(regression guard — was already correct before this fix)'u1'@'127.0.0.1') to confirm the host is also expanded correctlyBasing the PR against the correct MariaDB version
This fix targets the binlog writing path in
sql/sql_acl.ccand applies to all supported versions where the bug is present.Copyright
All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services, Inc.