summaryrefslogtreecommitdiff
path: root/sql/sql_acl.cc
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-10-18 15:54:41 -0700
committerSergei Golubchik <sergii@pisem.net>2013-10-18 15:54:41 -0700
commitcb9d3bec4645fc17be233d37677144926317f028 (patch)
tree5184d5820f0965b5e0f11e065f16b15cfea80b61 /sql/sql_acl.cc
parent40c43c395bd931dcb9c2ec132f83dd9d610e43d6 (diff)
downloadmariadb-git-cb9d3bec4645fc17be233d37677144926317f028.tar.gz
post-review changes
Diffstat (limited to 'sql/sql_acl.cc')
-rw-r--r--sql/sql_acl.cc60
1 files changed, 34 insertions, 26 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 1e784ca9092..241207819dd 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1458,7 +1458,7 @@ void acl_free(bool end)
my_hash_free(&acl_roles);
free_root(&mem,MYF(0));
delete_dynamic(&acl_hosts);
- delete_dynamic_recursive(&acl_users, (FREE_FUNC) free_acl_user);
+ delete_dynamic_with_callback(&acl_users, (FREE_FUNC) free_acl_user);
delete_dynamic(&acl_dbs);
delete_dynamic(&acl_wild_hosts);
delete_dynamic(&acl_proxy_users);
@@ -1574,11 +1574,10 @@ my_bool acl_reload(THD *thd)
my_hash_free(&old_acl_roles);
free_root(&old_mem,MYF(0));
delete_dynamic(&old_acl_hosts);
- delete_dynamic_recursive(&old_acl_users, (FREE_FUNC) free_acl_user);
+ delete_dynamic_with_callback(&old_acl_users, (FREE_FUNC) free_acl_user);
delete_dynamic(&old_acl_proxy_users);
delete_dynamic(&old_acl_dbs);
my_hash_free(&old_acl_roles_mappings);
- my_hash_free(&old_acl_roles_mappings);
}
if (old_initialized)
mysql_mutex_unlock(&acl_cache->lock);
@@ -2407,9 +2406,9 @@ static void remove_role_user_mapping(ACL_USER_BASE *grantee, ACL_ROLE *role)
{
if (role == *dynamic_element(&grantee->role_grants, idx_user, ACL_ROLE**))
{
+ DBUG_ASSERT(!deleted_user);
delete_dynamic_element(&grantee->role_grants, idx_user);
- deleted_user= true;
- break;
+ IF_DBUG(deleted_user= true, break);
}
}
@@ -2418,9 +2417,9 @@ static void remove_role_user_mapping(ACL_USER_BASE *grantee, ACL_ROLE *role)
if (grantee == *dynamic_element(&role->parent_grantee, idx_role,
ACL_USER_BASE**))
{
+ DBUG_ASSERT(!deleted_role);
delete_dynamic_element(&role->parent_grantee, idx_role);
- deleted_role= true;
- break;
+ IF_DBUG(deleted_role= true, break);
}
}
@@ -4535,16 +4534,29 @@ static void propagate_role_grants(ACL_ROLE *role,
privieges for all roles granted to a specific grantee, *before*
merging privileges for this grantee. In other words, we must visit all
parent nodes of a specific node, before descencing into this node.
- And not just "all parent nodes", but only parent nodes that are part of
- the subgraph we're inderested in. For example, if both role1 and role2
- are granted to role3, then role3 has two parent nodes. But when granting
- a privilege to role1, we're only looking at a subgraph that includes
- role1 and role3 (role2 cannot be possibly affected by that grant
- statement). In this subgraph role3 has only one parent.
-
- Thus, we do two graph traversals here. First we only count parents that
- are part of the subgraph. On the second traversal we decrement the counter
- and actually merge privileges for a node when a counter drops to zero.
+
+ For example, if role1 is granted to role2 and role3, and role3 is
+ granted to role2, after "GRANT ... role1", we cannot merge privileges
+ for role2, until role3 is merged. The counter will be 0 for role1, 2
+ for role2, 1 for role3. Traversal will start from role1, go to role2,
+ decrement the counter, backtrack, go to role3, merge it, go to role2
+ again, merge it.
+
+ And the counter is not just "all parent nodes", but only parent nodes
+ that are part of the subgraph we're interested in. For example, if
+ both roleA and roleB are granted to roleC, then roleC has two parent
+ nodes. But when granting a privilege to roleA, we're only looking at a
+ subgraph that includes roleA and roleC (roleB cannot be possibly
+ affected by that grant statement). In this subgraph roleC has only one
+ parent.
+
+ (on the other hand, in acl_load we want to update all roles, and
+ the counter is exactly equal to the number of all parent nodes)
+
+ Thus, we do two graph traversals here. First we only count parents
+ that are part of the subgraph. On the second traversal we decrement
+ the counter and actually merge privileges for a node when a counter
+ drops to zero.
*/
traverse_role_graph_up(role, &data, init_role_for_merging, count_subgraph_nodes);
traverse_role_graph_up(role, &data, NULL, merge_role_privileges);
@@ -5251,7 +5263,8 @@ static bool merge_role_routine_grant_privileges(ACL_ROLE *grantee,
/**
update privileges of the 'grantee' from all roles, granted to it
*/
-static int merge_role_privileges(ACL_ROLE *role, ACL_ROLE *grantee, void *context)
+static int merge_role_privileges(ACL_ROLE *role __attribute__((unused)),
+ ACL_ROLE *grantee, void *context)
{
PRIVS_TO_MERGE *data= (PRIVS_TO_MERGE *)context;
@@ -5824,6 +5837,9 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
C_STRING_WITH_LEN("roles_mapping"),
"roles_mapping", TL_WRITE);
+ if (open_and_lock_tables(thd, &tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
+ DBUG_RETURN(TRUE); /* purecov: deadcode */
+
mysql_rwlock_wrlock(&LOCK_grant);
mysql_mutex_lock(&acl_cache->lock);
if (!(role= find_acl_role(rolename.str)))
@@ -5843,14 +5859,6 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
DBUG_RETURN(TRUE);
}
- if (open_and_lock_tables(thd, &tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
- { // Should never happen
- mysql_mutex_unlock(&acl_cache->lock);
- mysql_rwlock_unlock(&LOCK_grant);
- my_error(ER_NO_SUCH_TABLE, MYF(0), "mysql", "roles_mapping");
- DBUG_RETURN(TRUE); /* purecov: deadcode */
- }
-
while ((user= user_list++))
{
role_as_user= NULL;