mariadb/mysql-test/suite/rpl/r/rpl_grant.result
Brandon Nesterenko 11f228cbb2 MDEV-38506: Failed GRANT on a procedure breaks replication
When GRANT EXECUTE ON PROCEDURE fails on the master, it will
erroneously be replicated and executed successfully on the slave.
This both breaks replication and is a security violation.

The underlying issue is that a failed GRANT EXECUTE ON PROCEDURE will
still be replicated when sql_mode does not have NO_AUTO_CREATE_USER.
This is because the function mysql_routine_grant() does not check if an
error occured while performing the GRANT before binlogging, it simply
always binlogs.

This patch fixes this problem by checking if an error happened
previously before binlogging, and if so, then skip binlogging.

Note there is still a broader issue in this area leading to replication
divergence. Reported in MDEV-29848, a partially-completed GRANT
statment (where some earlier GRANTS succeed and a later fails) will not
binlog. Note this affects all grant types, whereas the issue addressed
in this patch is limited to GRANT EXECUTE ON PROCEDURE. This patch
makes GRANT EXECUTE ON PROCEDURE binlogging behavior consistent with
the other grant types. A separate follow-up patch will address the
broader MDEV-29848 issue.

Also note that a test case in rpl_do_grant.test took advantage of
MDEV-38506 so a partially-failing REVOKE EXECUTE ON PROCEDURE would
still replicate.  This test case is disabled with a TODO note to
re-enable it once MDEV-29848 is fixed

Reviewed-by: Sergei Golubchik <serg@mariadb.org>
Signed-off-by: Brandon Nesterenko <brandon.nesterenko@mariadb.com>
2026-01-21 14:31:21 -07:00

70 lines
2.2 KiB
Text

include/master-slave.inc
[connection master]
connection master;
CREATE USER dummy@localhost;
CREATE USER dummy1@localhost, dummy2@localhost;
SELECT user, host FROM mysql.user WHERE user like 'dummy%';
User Host
dummy localhost
dummy1 localhost
dummy2 localhost
SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%';
COUNT(*)
3
connection slave;
**** On Slave ****
SELECT user,host FROM mysql.user WHERE user like 'dummy%';
User Host
dummy localhost
dummy1 localhost
dummy2 localhost
SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%';
COUNT(*)
3
connection master;
DROP USER nonexisting@localhost;
ERROR HY000: Operation DROP USER failed for 'nonexisting'@'localhost'
DROP USER nonexisting@localhost, dummy@localhost;
ERROR HY000: Operation DROP USER failed for 'nonexisting'@'localhost'
DROP USER dummy1@localhost, dummy2@localhost;
SELECT user, host FROM mysql.user WHERE user like 'dummy%';
User Host
SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%';
COUNT(*)
0
connection slave;
SELECT user,host FROM mysql.user WHERE user like 'dummy%';
User Host
SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%';
COUNT(*)
0
#
# MDEV-38506: Failed GRANT on a procedure breaks replication
#
# Disable NO_AUTO_CREATE_USER so grant will auto-create users
connection master;
SET @old_sql_mode= @@GLOBAL.sql_mode;
SET GLOBAL sql_mode='';
# Create new stored procedure for GRANT EXECUTE ON PROCEDURE
CREATE PROCEDURE test.sp() SELECT 1;
# Create a new user with limited privileges to grant sp execution
CREATE USER 'test_user'@'%' IDENTIFIED BY 'somepass';
GRANT EXECUTE ON test.* TO 'test_user'@'%' WITH GRANT OPTION;
connect con_test_user,localhost,test_user,somepass;
GRANT EXECUTE ON PROCEDURE test.sp TO 'nonexistentuser'@'';
ERROR 42000: You are not allowed to create a user with GRANT
# Ensuring the failed GRANT is not replicated..
include/rpl_sync.inc
connection master;
connection slave;
SHOW GRANTS for 'nonexistentuser'@'';
ERROR 42000: There is no such grant defined for user 'nonexistentuser' on host '%'
# ..PASS
connection master;
disconnect con_test_user;
SET GLOBAL sql_mode= @old_sql_mode;
DROP USER test_user@'%';
DROP PROCEDURE test.sp;
# End of MDEV-38506 test case
include/rpl_end.inc
# End of rpl_grant.test