Commit cb9d3bec authored by Sergei Golubchik's avatar Sergei Golubchik

post-review changes

parent 40c43c39
...@@ -794,7 +794,7 @@ extern my_bool allocate_dynamic(DYNAMIC_ARRAY *array, uint max_elements); ...@@ -794,7 +794,7 @@ extern my_bool allocate_dynamic(DYNAMIC_ARRAY *array, uint max_elements);
extern void get_dynamic(DYNAMIC_ARRAY *array,uchar * element,uint array_index); extern void get_dynamic(DYNAMIC_ARRAY *array,uchar * element,uint array_index);
extern void delete_dynamic(DYNAMIC_ARRAY *array); extern void delete_dynamic(DYNAMIC_ARRAY *array);
extern void delete_dynamic_element(DYNAMIC_ARRAY *array, uint array_index); extern void delete_dynamic_element(DYNAMIC_ARRAY *array, uint array_index);
extern void delete_dynamic_recursive(DYNAMIC_ARRAY *array, FREE_FUNC f); extern void delete_dynamic_with_callback(DYNAMIC_ARRAY *array, FREE_FUNC f);
extern void freeze_size(DYNAMIC_ARRAY *array); extern void freeze_size(DYNAMIC_ARRAY *array);
extern int get_index_dynamic(DYNAMIC_ARRAY *array, uchar * element); extern int get_index_dynamic(DYNAMIC_ARRAY *array, uchar * element);
#define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element) #define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element)
......
...@@ -326,12 +326,12 @@ void delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx) ...@@ -326,12 +326,12 @@ void delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx)
element, before releasing the memory element, before releasing the memory
SYNOPSIS SYNOPSIS
delete_dynamic_recursive() delete_dynamic_with_callback()
array array
f The function to be called on every element before f The function to be called on every element before
deleting the array; deleting the array;
*/ */
void delete_dynamic_recursive(DYNAMIC_ARRAY *array, FREE_FUNC f) { void delete_dynamic_with_callback(DYNAMIC_ARRAY *array, FREE_FUNC f) {
uint i; uint i;
char *ptr= (char*) array->buffer; char *ptr= (char*) array->buffer;
for (i= 0; i < array->elements; i++, ptr+= array->size_of_element) { for (i= 0; i < array->elements; i++, ptr+= array->size_of_element) {
......
...@@ -1458,7 +1458,7 @@ void acl_free(bool end) ...@@ -1458,7 +1458,7 @@ void acl_free(bool end)
my_hash_free(&acl_roles); my_hash_free(&acl_roles);
free_root(&mem,MYF(0)); free_root(&mem,MYF(0));
delete_dynamic(&acl_hosts); 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_dbs);
delete_dynamic(&acl_wild_hosts); delete_dynamic(&acl_wild_hosts);
delete_dynamic(&acl_proxy_users); delete_dynamic(&acl_proxy_users);
...@@ -1574,11 +1574,10 @@ my_bool acl_reload(THD *thd) ...@@ -1574,11 +1574,10 @@ my_bool acl_reload(THD *thd)
my_hash_free(&old_acl_roles); my_hash_free(&old_acl_roles);
free_root(&old_mem,MYF(0)); free_root(&old_mem,MYF(0));
delete_dynamic(&old_acl_hosts); 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_proxy_users);
delete_dynamic(&old_acl_dbs); delete_dynamic(&old_acl_dbs);
my_hash_free(&old_acl_roles_mappings); my_hash_free(&old_acl_roles_mappings);
my_hash_free(&old_acl_roles_mappings);
} }
if (old_initialized) if (old_initialized)
mysql_mutex_unlock(&acl_cache->lock); mysql_mutex_unlock(&acl_cache->lock);
...@@ -2407,9 +2406,9 @@ static void remove_role_user_mapping(ACL_USER_BASE *grantee, ACL_ROLE *role) ...@@ -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**)) if (role == *dynamic_element(&grantee->role_grants, idx_user, ACL_ROLE**))
{ {
DBUG_ASSERT(!deleted_user);
delete_dynamic_element(&grantee->role_grants, idx_user); delete_dynamic_element(&grantee->role_grants, idx_user);
deleted_user= true; IF_DBUG(deleted_user= true, break);
break;
} }
} }
...@@ -2418,9 +2417,9 @@ static void remove_role_user_mapping(ACL_USER_BASE *grantee, ACL_ROLE *role) ...@@ -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, if (grantee == *dynamic_element(&role->parent_grantee, idx_role,
ACL_USER_BASE**)) ACL_USER_BASE**))
{ {
DBUG_ASSERT(!deleted_role);
delete_dynamic_element(&role->parent_grantee, idx_role); delete_dynamic_element(&role->parent_grantee, idx_role);
deleted_role= true; IF_DBUG(deleted_role= true, break);
break;
} }
} }
...@@ -4535,16 +4534,29 @@ static void propagate_role_grants(ACL_ROLE *role, ...@@ -4535,16 +4534,29 @@ static void propagate_role_grants(ACL_ROLE *role,
privieges for all roles granted to a specific grantee, *before* privieges for all roles granted to a specific grantee, *before*
merging privileges for this grantee. In other words, we must visit all merging privileges for this grantee. In other words, we must visit all
parent nodes of a specific node, before descencing into this node. 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 For example, if role1 is granted to role2 and role3, and role3 is
are granted to role3, then role3 has two parent nodes. But when granting granted to role2, after "GRANT ... role1", we cannot merge privileges
a privilege to role1, we're only looking at a subgraph that includes for role2, until role3 is merged. The counter will be 0 for role1, 2
role1 and role3 (role2 cannot be possibly affected by that grant for role2, 1 for role3. Traversal will start from role1, go to role2,
statement). In this subgraph role3 has only one parent. decrement the counter, backtrack, go to role3, merge it, go to role2
again, merge it.
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 the counter is not just "all parent nodes", but only parent nodes
and actually merge privileges for a node when a counter drops to zero. 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, init_role_for_merging, count_subgraph_nodes);
traverse_role_graph_up(role, &data, NULL, merge_role_privileges); traverse_role_graph_up(role, &data, NULL, merge_role_privileges);
...@@ -5251,7 +5263,8 @@ static bool merge_role_routine_grant_privileges(ACL_ROLE *grantee, ...@@ -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 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; PRIVS_TO_MERGE *data= (PRIVS_TO_MERGE *)context;
...@@ -5824,6 +5837,9 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) ...@@ -5824,6 +5837,9 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
C_STRING_WITH_LEN("roles_mapping"), C_STRING_WITH_LEN("roles_mapping"),
"roles_mapping", TL_WRITE); "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_rwlock_wrlock(&LOCK_grant);
mysql_mutex_lock(&acl_cache->lock); mysql_mutex_lock(&acl_cache->lock);
if (!(role= find_acl_role(rolename.str))) if (!(role= find_acl_role(rolename.str)))
...@@ -5843,14 +5859,6 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) ...@@ -5843,14 +5859,6 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke)
DBUG_RETURN(TRUE); 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++)) while ((user= user_list++))
{ {
role_as_user= NULL; role_as_user= NULL;
......
...@@ -419,6 +419,7 @@ void init_update_queries(void) ...@@ -419,6 +419,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_DROP_USER]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_DROP_USER]|= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_RENAME_USER]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_RENAME_USER]|= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_CREATE_ROLE]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_CREATE_ROLE]|= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_DROP_ROLE]|= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_REVOKE_ALL]= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_REVOKE_ALL]= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_REVOKE]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_REVOKE]|= CF_AUTO_COMMIT_TRANS;
sql_command_flags[SQLCOM_REVOKE_ROLE]|= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_REVOKE_ROLE]|= CF_AUTO_COMMIT_TRANS;
...@@ -518,7 +519,8 @@ static void handle_bootstrap_impl(THD *thd) ...@@ -518,7 +519,8 @@ static void handle_bootstrap_impl(THD *thd)
thd_proc_info(thd, 0); thd_proc_info(thd, 0);
thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME)); thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME));
thd->security_ctx->priv_user[0]= thd->security_ctx->priv_host[0]=0; thd->security_ctx->priv_user[0]= thd->security_ctx->priv_host[0]=
thd->security_ctx->priv_role[0]= 0;
/* /*
Make the "client" handle multiple results. This is necessary Make the "client" handle multiple results. This is necessary
to enable stored procedures with SELECTs and Dynamic SQL to enable stored procedures with SELECTs and Dynamic SQL
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment