Skip to content

Commit a2bd45b

Browse files
committed
MDEV-38506: (Patch) Failed GRANT on a procedure breaks replication
A failed GRANT on a procedure will 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 on a procedure 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. Reviewed-by: TODO Signed-off-by: Brandon Nesterenko <[email protected]>
1 parent b35af31 commit a2bd45b

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

mysql-test/suite/rpl/r/rpl_grant.result

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,33 @@ User Host
3838
SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%';
3939
COUNT(*)
4040
0
41+
#
42+
# MDEV-38506: Failed GRANT on a procedure breaks replication
43+
#
44+
# Disable NO_AUTO_CREATE_USER so grant will auto-create users
45+
connection master;
46+
SET @old_sql_mode= @@GLOBAL.sql_mode;
47+
SET GLOBAL sql_mode='';
48+
# Create new stored procedure sp to be granted to new role test_role
49+
CREATE PROCEDURE test.sp() SELECT 1;
50+
# Create a new user with limited privileges to grant sp execution to test_role
51+
CREATE USER 'test_user'@'%' IDENTIFIED BY 'somepass';
52+
GRANT EXECUTE ON test.* TO 'test_user'@'%' WITH GRANT OPTION;
53+
connect con_test_user,localhost,test_user,somepass;
54+
GRANT EXECUTE ON PROCEDURE test.sp TO 'nonexistentuser'@'';
55+
ERROR 42000: You are not allowed to create a user with GRANT
56+
# Ensuring the failed GRANT is not replicated..
57+
include/rpl_sync.inc
58+
connection master;
59+
connection slave;
60+
SHOW GRANTS for 'nonexistentuser'@'';
61+
ERROR 42000: There is no such grant defined for user 'nonexistentuser' on host '%'
62+
# ..PASS
63+
connection master;
64+
disconnect con_test_user;
65+
SET GLOBAL sql_mode= @old_sql_mode;
66+
DROP USER test_user@'%';
67+
DROP PROCEDURE test.sp;
68+
# End of MDEV-38506 test case
4169
include/rpl_end.inc
70+
# End of rpl_grant.test

sql/sql_acl.cc

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7428,7 +7428,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list,
74287428
List_iterator <LEX_USER> str_list (user_list);
74297429
LEX_USER *Str, *tmp_Str;
74307430
bool create_new_users= 0;
7431-
int result;
7431+
bool result;
74327432
const char *db_name, *table_name;
74337433
DBUG_ENTER("mysql_routine_grant");
74347434

@@ -7519,11 +7519,9 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list,
75197519
thd->mem_root= old_root;
75207520
mysql_mutex_unlock(&acl_cache->lock);
75217521

7522-
if (write_to_binlog)
7523-
{
7524-
if (write_bin_log(thd, FALSE, thd->query(), thd->query_length()))
7525-
result= TRUE;
7526-
}
7522+
if (write_to_binlog && !result)
7523+
result= static_cast<bool>(
7524+
write_bin_log(thd, FALSE, thd->query(), thd->query_length()));
75277525

75287526
mysql_rwlock_unlock(&LOCK_grant);
75297527

0 commit comments

Comments
 (0)