Commit d1269934 authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-4951 drop user leaves privileges

It's safe to delete from HASH when traversing it *backwards*, but not *forwards*.
parent 1906f138
...@@ -1615,8 +1615,8 @@ ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 't ...@@ -1615,8 +1615,8 @@ ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 't
show grants for mysqluser10@localhost; show grants for mysqluser10@localhost;
Grants for mysqluser10@localhost Grants for mysqluser10@localhost
GRANT USAGE ON *.* TO 'mysqluser10'@'localhost' GRANT USAGE ON *.* TO 'mysqluser10'@'localhost'
GRANT SELECT ON `mysqltest1`.`t22` TO 'mysqluser10'@'localhost'
GRANT SELECT ON `mysqltest1`.`t11` TO 'mysqluser10'@'localhost' GRANT SELECT ON `mysqltest1`.`t11` TO 'mysqluser10'@'localhost'
GRANT SELECT ON `mysqltest1`.`t22` TO 'mysqluser10'@'localhost'
GRANT EXECUTE ON PROCEDURE `mysqltest1`.`p1` TO 'mysqluser10'@'localhost' GRANT EXECUTE ON PROCEDURE `mysqltest1`.`p1` TO 'mysqluser10'@'localhost'
GRANT EXECUTE ON FUNCTION `mysqltest1`.`f1` TO 'mysqluser10'@'localhost' GRANT EXECUTE ON FUNCTION `mysqltest1`.`f1` TO 'mysqluser10'@'localhost'
select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser10' and host='localhost'; select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser10' and host='localhost';
......
...@@ -1154,6 +1154,8 @@ drop user olga@localhost; ...@@ -1154,6 +1154,8 @@ drop user olga@localhost;
drop user pjotr@localhost; drop user pjotr@localhost;
drop user quintessa@localhost; drop user quintessa@localhost;
drop database mysqltest1; drop database mysqltest1;
select * from information_schema.table_privileges;
GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
End of 5.0 tests. End of 5.0 tests.
DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v1;
DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t1;
......
...@@ -1595,6 +1595,12 @@ disconnect root; ...@@ -1595,6 +1595,12 @@ disconnect root;
connection default; connection default;
#
# MDEV-4951 drop user leaves privileges
#
#verify that no privileges were left after the above
select * from information_schema.table_privileges;
--echo End of 5.0 tests. --echo End of 5.0 tests.
......
...@@ -6137,8 +6137,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, ...@@ -6137,8 +6137,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
LEX_USER *user_from, LEX_USER *user_to) LEX_USER *user_from, LEX_USER *user_to)
{ {
int result= 0; int result= 0;
uint idx; int idx;
uint elements; int elements;
const char *user; const char *user;
const char *host; const char *host;
ACL_USER *acl_user= NULL; ACL_USER *acl_user= NULL;
...@@ -6187,8 +6187,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, ...@@ -6187,8 +6187,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
DBUG_PRINT("loop",("scan struct: %u search user: '%s' host: '%s'", DBUG_PRINT("loop",("scan struct: %u search user: '%s' host: '%s'",
struct_no, user_from->user.str, user_from->host.str)); struct_no, user_from->user.str, user_from->host.str));
#endif #endif
/* Loop over all elements. */ /* Loop over all elements *backwards* (see the comment below). */
for (idx= 0; idx < elements; idx++) for (idx= elements - 1; idx >= 0; idx--)
{ {
/* /*
Get a pointer to the element. Get a pointer to the element.
...@@ -6239,6 +6239,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, ...@@ -6239,6 +6239,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
result= 1; /* At least one element found. */ result= 1; /* At least one element found. */
if ( drop ) if ( drop )
{ {
elements--;
switch ( struct_no ) { switch ( struct_no ) {
case USER_ACL: case USER_ACL:
delete_dynamic_element(&acl_users, idx); delete_dynamic_element(&acl_users, idx);
...@@ -6252,6 +6253,15 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, ...@@ -6252,6 +6253,15 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
case PROC_PRIVILEGES_HASH: case PROC_PRIVILEGES_HASH:
case FUNC_PRIVILEGES_HASH: case FUNC_PRIVILEGES_HASH:
my_hash_delete(grant_name_hash, (uchar*) grant_name); my_hash_delete(grant_name_hash, (uchar*) grant_name);
/*
In our HASH implementation on deletion one elements
is moved into a place where a deleted element was,
and the last element is moved into the empty space.
Thus we need to re-examine the current element, but
we don't have to restart the search from the beginning.
*/
if (idx != elements)
idx++;
break; break;
case PROXY_USERS_ACL: case PROXY_USERS_ACL:
...@@ -6259,21 +6269,6 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, ...@@ -6259,21 +6269,6 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
break; break;
} }
elements--;
/*
- If we are iterating through an array then we just have moved all
elements after the current element one position closer to its head.
This means that we have to take another look at the element at
current position as it is a new element from the array's tail.
- If we are iterating through a hash the current element was replaced
with one of elements from the tail. So we also have to take a look
at the new element in current position.
Note that in our HASH implementation hash_delete() won't move any
elements with position after current one to position before the
current (i.e. from the tail to the head), so it is safe to continue
iteration without re-starting.
*/
idx--;
} }
else if ( user_to ) else if ( user_to )
{ {
...@@ -6314,15 +6309,15 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, ...@@ -6314,15 +6309,15 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
my_hash_update(grant_name_hash, (uchar*) grant_name, (uchar*) old_key, my_hash_update(grant_name_hash, (uchar*) grant_name, (uchar*) old_key,
old_key_length); old_key_length);
/* /*
hash_update() operation could have moved element from the tail hash_update() operation could have moved element from the tail or
of the hash to the current position. So we need to take a look the head of the hash to the current position. But it can never
at the element in current position once again. move an element from the head to the tail or from the tail to the
Thanks to the fact that hash_update() for our HASH implementation head over the current element.
won't move any elements from the tail of the hash to the positions So we need to examine the current element once again, but
before the current one (a.k.a. head) it is safe to continue we don't need to restart the search from the beginning.
iteration without restarting.
*/ */
idx--; if (idx != elements)
idx++;
break; break;
} }
......
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