#
# MDEV-40656 REVOKE DENY FROM PUBLIC can lock itself out
#
# DENY TO PUBLIC denies everyone, including whoever tries to revoke
# it. Allowed anyway when the revoker can UPDATE mysql.global_priv,
# same as hand-editing it. Checked at every scope: global, db, table,
# column, routine.
#
CREATE TABLE test.t1 (id INT, data INT);
INSERT INTO test.t1 VALUES (1, 100);
CREATE PROCEDURE test.p1() BEGIN SELECT 1; END|
#
# Same session: no bypass needed, privileges aren't re-read yet
#
DENY SELECT ON test.t1 TO PUBLIC;
REVOKE DENY SELECT ON test.t1 FROM PUBLIC;
#
# Table level
#
CREATE USER u_table@localhost;
GRANT SELECT ON test.t1 TO u_table@localhost;
DENY SELECT ON test.t1 TO PUBLIC;
connect con_table1, localhost, u_table,,test;
SELECT * FROM t1; ERROR42000: SELECT command denied to user 'u_table'@'localhost' for table `test`.`t1`
REVOKE DENY SELECT ON test.t1 FROM PUBLIC; ERROR42000: SELECT, GRANT command denied to user 'u_table'@'localhost' for table `test`.`t1`
disconnect con_table1;
connection default;
GRANT UPDATE ON mysql.global_priv TO u_table@localhost;
connect con_table2, localhost, u_table,,test;
SELECT * FROM t1; ERROR42000: SELECT command denied to user 'u_table'@'localhost' for table `test`.`t1`
REVOKE DENY SELECT ON test.t1 FROM PUBLIC;
SELECT * FROM t1;
id data 1100
disconnect con_table2;
connection default;
REVOKE UPDATE ON mysql.global_priv FROM u_table@localhost;
DROP USER u_table@localhost;
#
# Column level
#
CREATE USER u_col@localhost;
GRANT SELECT ON test.t1 TO u_col@localhost;
DENY SELECT (data) ON test.t1 TO PUBLIC;
connect con_col1, localhost, u_col,,test;
SELECT data FROM t1; ERROR42000: SELECT command denied to user 'u_col'@'localhost' for column 'data' in table 't1'
REVOKE DENY SELECT (data) ON test.t1 FROM PUBLIC; ERROR42000: GRANT command denied to user 'u_col'@'localhost' for table `test`.`t1`
disconnect con_col1;
connection default;
GRANT UPDATE ON mysql.global_priv TO u_col@localhost;
connect con_col2, localhost, u_col,,test;
SELECT data FROM t1; ERROR42000: SELECT command denied to user 'u_col'@'localhost' for column 'data' in table 't1'
REVOKE DENY SELECT (data) ON test.t1 FROM PUBLIC;
SELECT data FROM t1;
data 100
disconnect con_col2;
connection default;
REVOKE UPDATE ON mysql.global_priv FROM u_col@localhost;
DROP USER u_col@localhost;
#
# DB level
#
CREATE USER u_db@localhost;
GRANT SELECT ON test.* TO u_db@localhost;
DENY SELECT ON test.* TO PUBLIC;
connect con_db1, localhost, u_db,,;
SELECT * FROM test.t1; ERROR42000: SELECT command denied to user 'u_db'@'localhost' for table `test`.`t1`
REVOKE DENY SELECT ON test.* FROM PUBLIC; ERROR42000: Access denied for user 'u_db'@'localhost' to database 'test'
disconnect con_db1;
connection default;
GRANT UPDATE ON mysql.global_priv TO u_db@localhost;
connect con_db2, localhost, u_db,,;
SELECT * FROM test.t1; ERROR42000: SELECT command denied to user 'u_db'@'localhost' for table `test`.`t1`
REVOKE DENY SELECT ON test.* FROM PUBLIC;
SELECT * FROM test.t1;
id data 1100
disconnect con_db2;
connection default;
REVOKE UPDATE ON mysql.global_priv FROM u_db@localhost;
DROP USER u_db@localhost;
#
# Global level
#
CREATE USER u_global@localhost;
GRANT SELECT ON *.* TO u_global@localhost;
DENY SELECT ON *.* TO PUBLIC;
connect con_global1, localhost, u_global,,;
SELECT * FROM test.t1; ERROR42000: SELECT command denied to user 'u_global'@'localhost' for table `test`.`t1`
REVOKE DENY SELECT ON *.* FROM PUBLIC; ERROR28000: Access denied for user 'u_global'@'localhost' (using password: NO)
disconnect con_global1;
connection default;
GRANT UPDATE ON mysql.global_priv TO u_global@localhost;
connect con_global2, localhost, u_global,,;
SELECT * FROM test.t1; ERROR42000: SELECT command denied to user 'u_global'@'localhost' for table `test`.`t1`
REVOKE DENY SELECT ON *.* FROM PUBLIC;
disconnect con_global2;
connection default;
# master_access is cached at connect; needs a reconnect to take effect
connect con_global3, localhost, u_global,,;
SELECT * FROM test.t1;
id data 1100
disconnect con_global3;
connection default;
REVOKE UPDATE ON mysql.global_priv FROM u_global@localhost;
DROP USER u_global@localhost;
#
# Routine level
#
CREATE USER u_proc@localhost;
GRANT EXECUTE ON PROCEDURE test.p1 TO u_proc@localhost;
DENY EXECUTE ON PROCEDURE test.p1 TO PUBLIC;
connect con_proc1, localhost, u_proc,,test;
CALL p1(); ERROR42000: execute command denied to user 'u_proc'@'localhost' for routine 'test.p1'
REVOKE DENY EXECUTE ON PROCEDURE test.p1 FROM PUBLIC; ERROR42000: execute command denied to user 'u_proc'@'localhost' for routine 'test.p1'
disconnect con_proc1;
connection default;
GRANT UPDATE ON mysql.global_priv TO u_proc@localhost;
connect con_proc2, localhost, u_proc,,test;
CALL p1(); ERROR42000: execute command denied to user 'u_proc'@'localhost' for routine 'test.p1'
REVOKE DENY EXECUTE ON PROCEDURE test.p1 FROM PUBLIC;
CALL p1(); 1 1
disconnect con_proc2;
connection default;
REVOKE UPDATE ON mysql.global_priv FROM u_proc@localhost;
DROP USER u_proc@localhost;
#
# A role is not PUBLIC: no bypass, even with UPDATE on mysql.global_priv
#
CREATE ROLE r1;
CREATE USER u_role@localhost;
GRANT r1 TO u_role@localhost;
GRANT SELECT ON test.t1 TO r1;
DENY SELECT ON test.t1 TO r1;
GRANT UPDATE ON mysql.global_priv TO u_role@localhost;
connect con_role, localhost, u_role,,; SET ROLE r1;
SELECT * FROM test.t1; ERROR42000: SELECT command denied to user 'u_role'@'localhost' for table `test`.`t1`
REVOKE DENY SELECT ON test.t1 FROM r1; ERROR42000: SELECT, GRANT command denied to user 'u_role'@'localhost' for table `test`.`t1`
disconnect con_role;
connection default;
REVOKE UPDATE ON mysql.global_priv FROM u_role@localhost;
REVOKE DENY SELECT ON test.t1 FROM r1;
DROP USER u_role@localhost;
DROP ROLE r1;
#
# Known limitation: denying the bypass's own privilege is unrecoverable
#
DENY UPDATE ON *.* TO PUBLIC;
disconnect default;
connect default, localhost, root,,;
# Should FAIL - root can't UPDATE anywhere either, including this table
UPDATE mysql.global_priv SET Priv=Priv WHERE User='PUBLIC'; ERROR42000: UPDATE command denied to user 'root'@'localhost' for table `mysql`.`global_priv`
# Should FAIL - no recovery via REVOKE DENY once UPDATE itself is denied
REVOKE DENY UPDATE ON *.* FROM PUBLIC; ERROR28000: Access denied for user 'root'@'localhost' (using password: NO)
# Recovery: DELETE was never denied
DELETE FROM mysql.global_priv WHERE User='PUBLIC';
FLUSH PRIVILEGES;
disconnect default;
connect default, localhost, root,,;
# UPDATE works again after reconnecting
UPDATE mysql.global_priv SET Priv=Priv WHERE User='root'AND Host='localhost';
#
# Cleanup
#
DROP PROCEDURE test.p1;
DROP TABLE test.t1;
DELETE FROM mysql.global_priv WHERE User='PUBLIC';
FLUSH PRIVILEGES;
# End of 13.1 tests
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.