mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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.
This commit is contained in:
committed by
Vicențiu-Marian Ciorbaru
parent
145932a57b
commit
7735ba7666
@ -5586,6 +5586,7 @@ static int count_subgraph_nodes(ACL_ROLE *role, ACL_ROLE *grantee, void *context
|
||||
}
|
||||
|
||||
static int merge_role_privileges(ACL_ROLE *, ACL_ROLE *, void *);
|
||||
static bool merge_one_role_privileges(ACL_ROLE *grantee, PRIVS_TO_MERGE what);
|
||||
|
||||
/**
|
||||
rebuild privileges of all affected roles
|
||||
@ -5604,6 +5605,11 @@ static void propagate_role_grants(ACL_ROLE *role,
|
||||
mysql_mutex_assert_owner(&acl_cache->lock);
|
||||
PRIVS_TO_MERGE data= { what, db, name };
|
||||
|
||||
/*
|
||||
Before updating grants to roles that inherit from this role, ensure that
|
||||
the effective grants on this role are up-to-date from *its* granted roles.
|
||||
*/
|
||||
merge_one_role_privileges(role, data);
|
||||
/*
|
||||
Changing privileges of a role causes all other roles that had
|
||||
this role granted to them to have their rights invalidated.
|
||||
@ -6393,11 +6399,12 @@ static int merge_role_privileges(ACL_ROLE *role __attribute__((unused)),
|
||||
return !changed; // don't recurse into the subgraph if privs didn't change
|
||||
}
|
||||
|
||||
static bool merge_one_role_privileges(ACL_ROLE *grantee)
|
||||
static
|
||||
bool merge_one_role_privileges(ACL_ROLE *grantee,
|
||||
PRIVS_TO_MERGE what)
|
||||
{
|
||||
PRIVS_TO_MERGE data= { PRIVS_TO_MERGE::ALL, 0, 0 };
|
||||
grantee->counter= 1;
|
||||
return merge_role_privileges(0, grantee, &data);
|
||||
return merge_role_privileges(0, grantee, &what);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
@ -7144,7 +7151,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
|
||||
Only need to propagate grants when granting/revoking a role to/from
|
||||
a role
|
||||
*/
|
||||
if (role_as_user && merge_one_role_privileges(role_as_user) == 0)
|
||||
if (role_as_user)
|
||||
propagate_role_grants(role_as_user, PRIVS_TO_MERGE::ALL);
|
||||
}
|
||||
|
||||
@ -9702,9 +9709,6 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
|
||||
size_t old_key_length= acl_role->user.length;
|
||||
if (drop)
|
||||
{
|
||||
/* all grants must be revoked from this role by now. propagate this */
|
||||
propagate_role_grants(acl_role, PRIVS_TO_MERGE::ALL);
|
||||
|
||||
// delete the role from cross-reference arrays
|
||||
for (uint i=0; i < acl_role->role_grants.elements; i++)
|
||||
{
|
||||
@ -9720,6 +9724,12 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
|
||||
remove_ptr_from_dynarray(&grantee->role_grants, acl_role);
|
||||
}
|
||||
|
||||
/* Remove all of the role_grants from this role. */
|
||||
delete_dynamic(&acl_role->role_grants);
|
||||
|
||||
/* all grants must be revoked from this role by now. propagate this */
|
||||
propagate_role_grants(acl_role, PRIVS_TO_MERGE::ALL);
|
||||
|
||||
my_hash_delete(&acl_roles, (uchar*) acl_role);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
Reference in New Issue
Block a user