Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 3 additions & 65 deletions mysql-test/suite/rpl/r/rpl_do_grant.result
Original file line number Diff line number Diff line change
Expand Up @@ -211,71 +211,9 @@ connection master;
DROP TABLE t1;
DROP PROCEDURE p1;
connection slave;
### ii) Test case in which REVOKE partially succeeds
connection master;
include/rpl_reset.inc
connection master;
CREATE TABLE t1(c1 INT);
CREATE PROCEDURE p1() SELECT * FROM t1 |
CREATE USER 'user49119'@'localhost';
GRANT EXECUTE ON PROCEDURE p1 TO 'user49119'@'localhost';
##############################################################
### Showing grants for both users: root and user49119 (master)
SHOW GRANTS FOR 'user49119'@'localhost';
Grants for user49119@localhost
GRANT USAGE ON *.* TO `user49119`@`localhost`
GRANT EXECUTE ON PROCEDURE `test`.`p1` TO `user49119`@`localhost`
SHOW GRANTS FOR CURRENT_USER;
Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO `root`@`localhost` WITH GRANT OPTION
GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION
##############################################################
connection slave;
##############################################################
### Showing grants for both users: root and user49119 (master)
SHOW GRANTS FOR 'user49119'@'localhost';
Grants for user49119@localhost
GRANT USAGE ON *.* TO `user49119`@`localhost`
GRANT EXECUTE ON PROCEDURE `test`.`p1` TO `user49119`@`localhost`
SHOW GRANTS FOR CURRENT_USER;
Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO `root`@`localhost` WITH GRANT OPTION
GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION
##############################################################
connection master;
## This statement will make the revoke fail because root has no
## execute grant. However, it will still revoke the grant for
## user49119.
REVOKE EXECUTE ON PROCEDURE p1 FROM 'user49119'@'localhost', 'root'@'localhost';
ERROR 42000: There is no such grant defined for user 'root' on host 'localhost' on routine 'p1'
##############################################################
### Showing grants for both users: root and user49119 (master)
### after revoke statement failure
SHOW GRANTS FOR 'user49119'@'localhost';
Grants for user49119@localhost
GRANT USAGE ON *.* TO `user49119`@`localhost`
SHOW GRANTS FOR CURRENT_USER;
Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO `root`@`localhost` WITH GRANT OPTION
GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION
##############################################################
connection slave;
#############################################################
### Showing grants for both users: root and user49119 (slave)
### after revoke statement failure (should match
SHOW GRANTS FOR 'user49119'@'localhost';
Grants for user49119@localhost
GRANT USAGE ON *.* TO `user49119`@`localhost`
SHOW GRANTS FOR CURRENT_USER;
Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO `root`@`localhost` WITH GRANT OPTION
GRANT PROXY ON ''@'%' TO 'root'@'localhost' WITH GRANT OPTION
##############################################################
connection master;
DROP TABLE t1;
DROP PROCEDURE p1;
DROP USER 'user49119'@'localhost';
connection slave;
#
# TODO: Re-enable test-case after fixing MDEV-29848
#
include/rpl_reset.inc
connection master;
grant all on *.* to foo@"1.2.3.4";
Expand Down
29 changes: 29 additions & 0 deletions mysql-test/suite/rpl/r/rpl_grant.result
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,33 @@ 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 sp to be granted to new role test_role
CREATE PROCEDURE test.sp() SELECT 1;
# Create a new user with limited privileges to grant sp execution to test_role
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
126 changes: 66 additions & 60 deletions mysql-test/suite/rpl/t/rpl_do_grant.test
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,11 @@ USE test;
# when binlogging is active, the master will not hit an
# assertion.
#
# ii) a test case that partially succeeds on the master will also
# partially succeed on the slave.
# ii) (DISABLED) To pass, this test case took advantage of a vulnerability,
# MDEV-38506. Please uncomment this test case when MDEV-29848 is fixed.
#
# test case that partially succeeds on the master will also
# partially succeed on the slave.
#
# - The revoke statement that partially succeeds tries to revoke
# an EXECUTE grant for two users, and only one of the user has
Expand Down Expand Up @@ -242,64 +245,67 @@ DROP PROCEDURE p1;

-- sync_slave_with_master

-- echo ### ii) Test case in which REVOKE partially succeeds

-- connection master
-- source include/rpl_reset.inc
-- connection master

CREATE TABLE t1(c1 INT);
DELIMITER |;
CREATE PROCEDURE p1() SELECT * FROM t1 |
DELIMITER ;|

CREATE USER 'user49119'@'localhost';
GRANT EXECUTE ON PROCEDURE p1 TO 'user49119'@'localhost';

-- echo ##############################################################
-- echo ### Showing grants for both users: root and user49119 (master)
SHOW GRANTS FOR 'user49119'@'localhost';
SHOW GRANTS FOR CURRENT_USER;
-- echo ##############################################################

-- sync_slave_with_master

-- echo ##############################################################
-- echo ### Showing grants for both users: root and user49119 (master)
SHOW GRANTS FOR 'user49119'@'localhost';
SHOW GRANTS FOR CURRENT_USER;
-- echo ##############################################################

-- connection master

-- echo ## This statement will make the revoke fail because root has no
-- echo ## execute grant. However, it will still revoke the grant for
-- echo ## user49119.
-- error ER_NONEXISTING_PROC_GRANT
REVOKE EXECUTE ON PROCEDURE p1 FROM 'user49119'@'localhost', 'root'@'localhost';

-- echo ##############################################################
-- echo ### Showing grants for both users: root and user49119 (master)
-- echo ### after revoke statement failure
SHOW GRANTS FOR 'user49119'@'localhost';
SHOW GRANTS FOR CURRENT_USER;
-- echo ##############################################################

-- sync_slave_with_master

-- echo #############################################################
-- echo ### Showing grants for both users: root and user49119 (slave)
-- echo ### after revoke statement failure (should match
SHOW GRANTS FOR 'user49119'@'localhost';
SHOW GRANTS FOR CURRENT_USER;
-- echo ##############################################################

-- connection master
DROP TABLE t1;
DROP PROCEDURE p1;
DROP USER 'user49119'@'localhost';

-- sync_slave_with_master
--echo #
--echo # TODO: Re-enable test-case after fixing MDEV-29848
--echo #
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrapping the test in if (0) { ... } would likely create a smaller diff

#-- echo ### ii) Test case in which REVOKE partially succeeds
#
#-- connection master
#-- source include/rpl_reset.inc
#-- connection master
#
#CREATE TABLE t1(c1 INT);
#DELIMITER |;
#CREATE PROCEDURE p1() SELECT * FROM t1 |
#DELIMITER ;|
#
#CREATE USER 'user49119'@'localhost';
#GRANT EXECUTE ON PROCEDURE p1 TO 'user49119'@'localhost';
#
#-- echo ##############################################################
#-- echo ### Showing grants for both users: root and user49119 (master)
#SHOW GRANTS FOR 'user49119'@'localhost';
#SHOW GRANTS FOR CURRENT_USER;
#-- echo ##############################################################
#
#-- sync_slave_with_master
#
#-- echo ##############################################################
#-- echo ### Showing grants for both users: root and user49119 (master)
#SHOW GRANTS FOR 'user49119'@'localhost';
#SHOW GRANTS FOR CURRENT_USER;
#-- echo ##############################################################
#
#-- connection master
#
#-- echo ## This statement will make the revoke fail because root has no
#-- echo ## execute grant. However, it will still revoke the grant for
#-- echo ## user49119.
#-- error ER_NONEXISTING_PROC_GRANT
#REVOKE EXECUTE ON PROCEDURE p1 FROM 'user49119'@'localhost', 'root'@'localhost';
#
#-- echo ##############################################################
#-- echo ### Showing grants for both users: root and user49119 (master)
#-- echo ### after revoke statement failure
#SHOW GRANTS FOR 'user49119'@'localhost';
#SHOW GRANTS FOR CURRENT_USER;
#-- echo ##############################################################
#
#-- sync_slave_with_master
#
#-- echo #############################################################
#-- echo ### Showing grants for both users: root and user49119 (slave)
#-- echo ### after revoke statement failure (should match)
#SHOW GRANTS FOR 'user49119'@'localhost';
#SHOW GRANTS FOR CURRENT_USER;
#-- echo ##############################################################
#
#-- connection master
#DROP TABLE t1;
#DROP PROCEDURE p1;
#DROP USER 'user49119'@'localhost';
#
#-- sync_slave_with_master

#
# Bug #51987 revoke privileges logs wrong error code
Expand Down
43 changes: 43 additions & 0 deletions mysql-test/suite/rpl/t/rpl_grant.test
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,47 @@ sync_slave_with_master;
SELECT user,host FROM mysql.user WHERE user like 'dummy%';
SELECT COUNT(*) FROM mysql.user WHERE user like 'dummy%';

--echo #
--echo # MDEV-38506: Failed GRANT on a procedure breaks replication
--echo #

--echo # Disable NO_AUTO_CREATE_USER so grant will auto-create users
connection master;
SET @old_sql_mode= @@GLOBAL.sql_mode;
SET GLOBAL sql_mode='';

--echo # Create new stored procedure for GRANT EXECUTE ON PROCEDURE
CREATE PROCEDURE test.sp() SELECT 1;

--echo # 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);
let $old_binlog_gtid= `SELECT @@global.gtid_binlog_pos`; # Tag the GTID before the failed GRANT
error ER_CANT_CREATE_USER_WITH_GRANT;
GRANT EXECUTE ON PROCEDURE test.sp TO 'nonexistentuser'@'';

--echo # Ensuring the failed GRANT is not replicated..
source include/rpl_sync.inc;
connection master;
let $new_binlog_gtid= `SELECT @@global.gtid_binlog_pos`;
if (`SELECT strcmp('$old_binlog_gtid', '$new_binlog_gtid') != 0`)
{
--echo # binlog_gtid_pos before GRANT: $old_binlog_gtid
--echo # binlog_gtid_pos after GRANT: $new_binlog_gtid
--die Failed GRANT was binlogged
}
connection slave;
error ER_NONEXISTING_GRANT;
SHOW GRANTS for 'nonexistentuser'@'';
--echo # ..PASS

connection master;
disconnect con_test_user;
SET GLOBAL sql_mode= @old_sql_mode;
DROP USER test_user@'%';
DROP PROCEDURE test.sp;
--echo # End of MDEV-38506 test case

--source include/rpl_end.inc
--echo # End of rpl_grant.test
2 changes: 1 addition & 1 deletion sql/sql_acl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7519,7 +7519,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list,
thd->mem_root= old_root;
mysql_mutex_unlock(&acl_cache->lock);

if (write_to_binlog)
if (write_to_binlog && !result)
{
if (write_bin_log(thd, FALSE, thd->query(), thd->query_length()))
result= TRUE;
Expand Down