summaryrefslogtreecommitdiff
path: root/sql/sql_acl.cc
diff options
context:
space:
mode:
authorVicențiu Ciorbaru <vicentiu@mariadb.org>2017-12-22 12:23:39 +0200
committerVicențiu Ciorbaru <vicentiu@mariadb.org>2017-12-22 12:23:39 +0200
commit985d2d393c285ecd4539cb579b680f7b91fdaa1a (patch)
tree8cabf6c09758c30df04de96ca98c7827d5665493 /sql/sql_acl.cc
parenta76a2522ec4f8c069827e038997387a8b8eb3a3a (diff)
parent461cf3e5a3c2d346d75b1407b285f8daf9d01f67 (diff)
downloadmariadb-git-985d2d393c285ecd4539cb579b680f7b91fdaa1a.tar.gz
Merge remote-tracking branch 'origin/10.1' into 10.2
Diffstat (limited to 'sql/sql_acl.cc')
-rw-r--r--sql/sql_acl.cc77
1 files changed, 50 insertions, 27 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 7f155ec7808..9c7eb8af736 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2851,37 +2851,42 @@ static void acl_insert_user(const char *user, const char *host,
}
-static void acl_update_db(const char *user, const char *host, const char *db,
+static bool acl_update_db(const char *user, const char *host, const char *db,
ulong privileges)
{
mysql_mutex_assert_owner(&acl_cache->lock);
+ bool updated= false;
+
for (uint i=0 ; i < acl_dbs.elements ; i++)
{
ACL_DB *acl_db=dynamic_element(&acl_dbs,i,ACL_DB*);
if ((!acl_db->user && !user[0]) ||
- (acl_db->user &&
- !strcmp(user,acl_db->user)))
+ (acl_db->user &&
+ !strcmp(user,acl_db->user)))
{
if ((!acl_db->host.hostname && !host[0]) ||
- (acl_db->host.hostname &&
- !strcmp(host, acl_db->host.hostname)))
+ (acl_db->host.hostname &&
+ !strcmp(host, acl_db->host.hostname)))
{
- if ((!acl_db->db && !db[0]) ||
- (acl_db->db && !strcmp(db,acl_db->db)))
+ if ((!acl_db->db && !db[0]) ||
+ (acl_db->db && !strcmp(db,acl_db->db)))
- {
- if (privileges)
+ {
+ if (privileges)
{
acl_db->access= privileges;
acl_db->initial_access= acl_db->access;
}
- else
- delete_dynamic_element(&acl_dbs,i);
- }
+ else
+ delete_dynamic_element(&acl_dbs,i);
+ updated= true;
+ }
}
}
}
+
+ return updated;
}
@@ -4373,9 +4378,21 @@ static int replace_db_table(TABLE *table, const char *db,
acl_cache->clear(1); // Clear privilege cache
if (old_row_exists)
acl_update_db(combo.user.str,combo.host.str,db,rights);
- else
- if (rights)
- acl_insert_db(combo.user.str,combo.host.str,db,rights);
+ else if (rights)
+ {
+ /*
+ If we did not have an already existing row, for users, we must always
+ insert an ACL_DB entry. For roles however, it is possible that one was
+ already created when DB privileges were propagated from other granted
+ roles onto the current role. For this case, first try to update the
+ existing entry, otherwise insert a new one.
+ */
+ if (!combo.is_role() ||
+ !acl_update_db(combo.user.str, combo.host.str, db, rights))
+ {
+ acl_insert_db(combo.user.str,combo.host.str,db,rights);
+ }
+ }
DBUG_RETURN(0);
/* This could only happen if the grant tables got corrupted */
@@ -6280,6 +6297,7 @@ static int merge_role_privileges(ACL_ROLE *role __attribute__((unused)),
{
PRIVS_TO_MERGE *data= (PRIVS_TO_MERGE *)context;
+ DBUG_ASSERT(grantee->counter > 0);
if (--grantee->counter)
return 1; // don't recurse into grantee just yet
@@ -7381,17 +7399,14 @@ end_index_init:
DBUG_RETURN(return_val);
}
-
-static my_bool role_propagate_grants_action(void *ptr,
- void *unused __attribute__((unused)))
+static my_bool collect_leaf_roles(void *role_ptr,
+ void *roles_array)
{
- ACL_ROLE *role= (ACL_ROLE *)ptr;
- if (role->counter)
- return 0;
-
- mysql_mutex_assert_owner(&acl_cache->lock);
- PRIVS_TO_MERGE data= { PRIVS_TO_MERGE::ALL, 0, 0 };
- traverse_role_graph_up(role, &data, NULL, merge_role_privileges);
+ ACL_ROLE *role= static_cast<ACL_ROLE *>(role_ptr);
+ Dynamic_array<ACL_ROLE *> *array=
+ static_cast<Dynamic_array<ACL_ROLE *> *>(roles_array);
+ if (!role->counter)
+ array->push(role);
return 0;
}
@@ -7461,7 +7476,15 @@ bool grant_reload(THD *thd)
}
mysql_mutex_lock(&acl_cache->lock);
- my_hash_iterate(&acl_roles, role_propagate_grants_action, NULL);
+ Dynamic_array<ACL_ROLE *> leaf_roles;
+ my_hash_iterate(&acl_roles, collect_leaf_roles, &leaf_roles);
+ PRIVS_TO_MERGE data= { PRIVS_TO_MERGE::ALL, 0, 0 };
+ for (size_t i= 0; i < leaf_roles.elements(); i++)
+ {
+ traverse_role_graph_up(leaf_roles.at(i), &data, NULL,
+ merge_role_privileges);
+ }
+
mysql_mutex_unlock(&acl_cache->lock);
mysql_rwlock_unlock(&LOCK_grant);
@@ -10181,13 +10204,13 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role)
}
}
- binlog= true;
if (replace_user_table(thd, tables.user_table(), *user_name, 0, 0, 1, 0))
{
append_user(thd, &wrong_users, user_name);
result= TRUE;
continue;
}
+ binlog= true;
// every created role is automatically granted to its creator-admin
if (handle_as_role)