Skip to content
Permalink
Browse files
MDEV-29458: Role grant commands do not propagate all grants
There was an issue in updating in-memory role datastructures when
propagating role grants.

The issue is that changing a particular role's privilege (on any
privilege level, global, database, etc.)
was done such that it overwrote the entire set of bits for that
particular level of privileges.

For example:
grant select on *.* to r1 -> sets the access bits to r1 to select,
regardless of what bits were present for role r1 (inherited from any
other roles).

Before this fix, the rights of role r1 were propagated to any roles r1
was granted to, however the propagated rights did *not* include the
complete rights r1 inherited from its own grants.

For example:
  grant r2 to r1;
  grant select on *.* to r2;
  grant insert on *.* to r1; # This command completely disregards the
                             # select privilege from r2.

In order to correct this, ensure that before rights are propagated
onwards, that the current's role rights have been updated from its
grants.

Additionally, the patch exposed a flaw in the DROP ROLE code.
When deleting a role we removed all its previous grants, but what
remained was the actual links of roles granted to the dropped role.
Having these links present when propagating grants meant that we would
have leftover ACL_xxx entries.

Ensure that the links are removed before propagating grants.
  • Loading branch information
cvicentiu committed Sep 14, 2022
1 parent 145932a commit 7735ba7
Show file tree
Hide file tree
Showing 4 changed files with 406 additions and 95 deletions.
@@ -56,7 +56,7 @@ connection default;
grant select on *.* to role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 19
Debug_role_merges_global 20
Debug_role_merges_db 0
Debug_role_merges_table 0
Debug_role_merges_column 0
@@ -106,7 +106,7 @@ connection default;
revoke select on *.* from role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_global 29
Debug_role_merges_db 0
Debug_role_merges_table 0
Debug_role_merges_column 0
@@ -124,8 +124,8 @@ connection default;
grant select on mysql.* to role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 8
Debug_role_merges_global 29
Debug_role_merges_db 9
Debug_role_merges_table 0
Debug_role_merges_column 0
Debug_role_merges_routine 0
@@ -164,8 +164,8 @@ connection default;
revoke select on mysql.* from role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 0
Debug_role_merges_column 0
Debug_role_merges_routine 0
@@ -177,9 +177,9 @@ connection default;
grant select on mysql.roles_mapping to role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 8
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 9
Debug_role_merges_column 0
Debug_role_merges_routine 0
connection foo;
@@ -217,9 +217,9 @@ connection default;
revoke select on mysql.roles_mapping from role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 16
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 17
Debug_role_merges_column 0
Debug_role_merges_routine 0
connection foo;
@@ -230,10 +230,10 @@ connection default;
grant select(User) on mysql.roles_mapping to role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 24
Debug_role_merges_column 8
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 26
Debug_role_merges_column 9
Debug_role_merges_routine 0
connection foo;
select count(*) from mysql.roles_mapping;
@@ -272,10 +272,10 @@ connection default;
grant select(Host) on mysql.roles_mapping to role3;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 30
Debug_role_merges_column 14
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 33
Debug_role_merges_column 16
Debug_role_merges_routine 0
connection foo;
select count(concat(User,Host,Role)) from mysql.roles_mapping;
@@ -312,10 +312,10 @@ connection default;
revoke select(User) on mysql.roles_mapping from role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 38
Debug_role_merges_column 22
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 41
Debug_role_merges_column 24
Debug_role_merges_routine 0
connection foo;
select count(concat(User,Host)) from mysql.roles_mapping;
@@ -327,10 +327,10 @@ connection default;
revoke select(Host) on mysql.roles_mapping from role3;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 44
Debug_role_merges_column 28
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 47
Debug_role_merges_column 30
Debug_role_merges_routine 0
connection foo;
select count(concat(Host)) from mysql.roles_mapping;
@@ -342,11 +342,11 @@ create function fn1() returns char(10) return "fn1";
grant execute on procedure test.pr1 to role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 44
Debug_role_merges_column 28
Debug_role_merges_routine 8
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 47
Debug_role_merges_column 30
Debug_role_merges_routine 9
connection foo;
call pr1();
ERROR 42000: execute command denied to user 'foo'@'localhost' for routine 'test.pr1'
@@ -360,11 +360,11 @@ connection default;
grant execute on function test.fn1 to role5;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 44
Debug_role_merges_column 28
Debug_role_merges_routine 13
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 47
Debug_role_merges_column 30
Debug_role_merges_routine 15
connection foo;
select fn1();
fn1()
@@ -373,11 +373,11 @@ connection default;
revoke execute on procedure test.pr1 from role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 44
Debug_role_merges_column 28
Debug_role_merges_routine 21
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 47
Debug_role_merges_column 30
Debug_role_merges_routine 23
connection foo;
call pr1();
ERROR 42000: execute command denied to user 'foo'@'localhost' for routine 'test.pr1'
@@ -388,11 +388,11 @@ connection default;
revoke execute on function test.fn1 from role5;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 44
Debug_role_merges_column 28
Debug_role_merges_routine 26
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 47
Debug_role_merges_column 30
Debug_role_merges_routine 28
connection foo;
select fn1();
ERROR 42000: execute command denied to user 'foo'@'localhost' for routine 'test.fn1'
@@ -403,67 +403,67 @@ drop function fn1;
grant select on mysql.roles_mapping to role3;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 50
Debug_role_merges_column 28
Debug_role_merges_routine 26
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 54
Debug_role_merges_column 30
Debug_role_merges_routine 28
grant select on mysql.roles_mapping to role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 53
Debug_role_merges_column 28
Debug_role_merges_routine 26
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 58
Debug_role_merges_column 30
Debug_role_merges_routine 28
revoke select on mysql.roles_mapping from role3;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 54
Debug_role_merges_column 28
Debug_role_merges_routine 26
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 59
Debug_role_merges_column 30
Debug_role_merges_routine 28
revoke select on mysql.roles_mapping from role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 16
Debug_role_merges_table 62
Debug_role_merges_column 28
Debug_role_merges_routine 26
Debug_role_merges_global 29
Debug_role_merges_db 17
Debug_role_merges_table 67
Debug_role_merges_column 30
Debug_role_merges_routine 28
grant select on mysql.* to role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 24
Debug_role_merges_table 62
Debug_role_merges_column 28
Debug_role_merges_routine 26
Debug_role_merges_global 29
Debug_role_merges_db 26
Debug_role_merges_table 67
Debug_role_merges_column 30
Debug_role_merges_routine 28
grant select on test.* to role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 32
Debug_role_merges_table 62
Debug_role_merges_column 28
Debug_role_merges_routine 26
Debug_role_merges_global 29
Debug_role_merges_db 35
Debug_role_merges_table 67
Debug_role_merges_column 30
Debug_role_merges_routine 28
revoke select on mysql.* from role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 40
Debug_role_merges_table 62
Debug_role_merges_column 28
Debug_role_merges_routine 26
Debug_role_merges_global 29
Debug_role_merges_db 43
Debug_role_merges_table 67
Debug_role_merges_column 30
Debug_role_merges_routine 28
revoke select on test.* from role1;
show status like 'debug%';
Variable_name Value
Debug_role_merges_global 27
Debug_role_merges_db 48
Debug_role_merges_table 62
Debug_role_merges_column 28
Debug_role_merges_routine 26
Debug_role_merges_global 29
Debug_role_merges_db 51
Debug_role_merges_table 67
Debug_role_merges_column 30
Debug_role_merges_routine 28
connection default;
drop user foo@localhost;
drop role role1;

0 comments on commit 7735ba7

Please sign in to comment.