[Commits] 22884d3: MDEV-7774: Crash when dropping user within rebuild_role_grants

vicentiu at mariadb.org vicentiu at mariadb.org
Fri Mar 13 20:14:59 EET 2015


revision-id: 22884d35e39ba078dddf5c15b42dd7e2ebb39c07
parent(s): 184f718fef0101a7559364cb97e22ee568e64c12
committer: Vicențiu Ciorbaru
branch nick: server
timestamp: 2015-03-13 20:12:22 +0200
message:

MDEV-7774: Crash when dropping user within rebuild_role_grants

The issue comes from not taking all possibilities to match an entry
within the roles_mapping HASH, when updating the data structure.

---
 mysql-test/suite/roles/create_and_drop_role.result | 18 +++++++++++++++
 mysql-test/suite/roles/create_and_drop_role.test   | 19 +++++++++++++++
 sql/sql_acl.cc                                     | 27 ++++++++++++++++++----
 3 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/mysql-test/suite/roles/create_and_drop_role.result b/mysql-test/suite/roles/create_and_drop_role.result
index 2974dd2..79c6f41 100644
--- a/mysql-test/suite/roles/create_and_drop_role.result
+++ b/mysql-test/suite/roles/create_and_drop_role.result
@@ -46,3 +46,21 @@ Note	1449	The user specified as a definer ('u1'@'%') does not exist
 create user foo at bar;
 drop user foo at bar;
 drop role r1;
+CREATE USER u1;
+CREATE ROLE r1;
+CREATE USER r1 at localhost;
+CREATE ROLE r2;
+GRANT r2 to r1;
+GRANT r2 to r1 at localhost;
+DROP ROLE r1;
+SELECT * FROM mysql.roles_mapping;
+Host	User	Role	Admin_option
+localhost	r1	r2	N
+localhost	root	r2	Y
+SHOW GRANTS FOR r1 at localhost;
+Grants for r1 at localhost
+GRANT r2 TO 'r1'@'localhost'
+GRANT USAGE ON *.* TO 'r1'@'localhost'
+DROP USER u1;
+DROP ROLE r2;
+DROP USER r1 at localhost;
diff --git a/mysql-test/suite/roles/create_and_drop_role.test b/mysql-test/suite/roles/create_and_drop_role.test
index 38f0407..0bf5b74 100644
--- a/mysql-test/suite/roles/create_and_drop_role.test
+++ b/mysql-test/suite/roles/create_and_drop_role.test
@@ -68,3 +68,22 @@ create user foo at bar;
 drop user foo at bar;
 drop role r1;
 
+#
+# MDEV-7774 Assertion `status == 0' fails when dropping in this order:
+#
+CREATE USER u1;
+CREATE ROLE r1;
+CREATE USER r1 at localhost;
+CREATE ROLE r2;
+GRANT r2 to r1;
+GRANT r2 to r1 at localhost;
+# MDEV-7774: Dropping in this order caused the crash.
+DROP ROLE r1;
+--sorted_result
+SELECT * FROM mysql.roles_mapping;
+SHOW GRANTS FOR r1 at localhost; # Related to MDEV-7774, also caused a crash, by
+                              # not updating the internal acl_roles_mapping
+                              # data structure correctly;
+DROP USER u1;
+DROP ROLE r2;
+DROP USER r1 at localhost;
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index e4975ac..1ef9b68 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -8802,10 +8802,29 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
     if (struct_no == ROLES_MAPPINGS_HASH)
     {
       const char* role= role_grant_pair->r_uname? role_grant_pair->r_uname: "";
-      if (user_from->is_role() ? strcmp(user_from->user.str, role) :
-          (strcmp(user_from->user.str, user) ||
-           my_strcasecmp(system_charset_info, user_from->host.str, host)))
-        continue;
+      if (user_from->is_role()) {
+        /* When searching for roles within the ROLES_MAPPINGS_HASH, we have
+           to check both the user field as well as the role field for a match.
+
+           It is possible to have a role granted to a role. If we are going
+           to modify the mapping entry, it needs to be done on either on the
+           "user" end (here represented by a role) or the "role" end. At least
+           one part must match.
+
+           If the "user" end has a not-empty host string, it can never match
+           as we are searching for a role here. A role always has an empty host
+           string.
+        */
+        if ((*host || strcmp(user_from->user.str, user)) &&
+            strcmp(user_from->user.str, role))
+          continue;
+      }
+      else
+      {
+        if (strcmp(user_from->user.str, user) ||
+            my_strcasecmp(system_charset_info, user_from->host.str, host))
+          continue;
+      }
     }
     else
     {


More information about the commits mailing list