From a4aec769b00a5a6c890305cb9f0d9c9f0c455511 Mon Sep 17 00:00:00 2001 From: "dellis@goetia.(none)" <> Date: Mon, 18 Oct 2004 20:25:47 -0500 Subject: [PATCH 1/2] sql_acl.cc: BUG #5831 Revoke privileges in a loop until no more privileges are revoked, because acl_dbs and column_priv_hash can re-organize during privilege removal. --- sql/sql_acl.cc | 122 +++++++++++++++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 49 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index fc252c1f5ac..07647f4eb82 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3623,67 +3623,91 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list) } /* Remove db access privileges */ - for (counter= 0 ; counter < acl_dbs.elements ; ) + /* + Because acl_dbs and column_priv_hash shrink and may re-order + as privileges are removed, removal occurs in a repeated loop + until no more privileges are revoked. + */ + while (1) { - const char *user,*host; - - acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); - if (!(user=acl_db->user)) - user= ""; - if (!(host=acl_db->host.hostname)) - host= ""; - - if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(system_charset_info, lex_user->host.str, host)) + int revoke= 0; + for (counter= 0 ; counter < acl_dbs.elements ; ) { - if (replace_db_table(tables[1].table, acl_db->db, *lex_user, ~0, 1)) - result= -1; - else - continue; + const char *user,*host; + + acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); + if (!(user=acl_db->user)) + user= ""; + if (!(host=acl_db->host.hostname)) + host= ""; + + if (!strcmp(lex_user->user.str,user) && + !my_strcasecmp(system_charset_info, lex_user->host.str, host)) + { + if (replace_db_table(tables[1].table, acl_db->db, *lex_user, ~0, 1)) + result= -1; + else + { + revoke= 1; + continue; + } + } + ++counter; } - ++counter; + if (!revoke) + break; } /* Remove column access */ - for (counter= 0 ; counter < column_priv_hash.records ; ) + while (1) { - const char *user,*host; - GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, - counter); - if (!(user=grant_table->user)) - user= ""; - if (!(host=grant_table->host)) - host= ""; - - if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(system_charset_info, lex_user->host.str, host)) + int revoke= 0; + for (counter= 0 ; counter < column_priv_hash.records ; ) { - if (replace_table_table(thd,grant_table,tables[2].table,*lex_user, - grant_table->db, - grant_table->tname, - ~0, 0, 1)) + const char *user,*host; + GRANT_TABLE *grant_table= (GRANT_TABLE*)hash_element(&column_priv_hash, + counter); + if (!(user=grant_table->user)) + user= ""; + if (!(host=grant_table->host)) + host= ""; + + if (!strcmp(lex_user->user.str,user) && + !my_strcasecmp(system_charset_info, lex_user->host.str, host)) { - result= -1; - } - else - { - if (grant_table->cols) - { - List<LEX_COLUMN> columns; - if (replace_column_table(grant_table,tables[3].table, *lex_user, - columns, - grant_table->db, - grant_table->tname, - ~0, 1)) - result= -1; - else - continue; - } + if (replace_table_table(thd,grant_table,tables[2].table,*lex_user, + grant_table->db, + grant_table->tname, + ~0, 0, 1)) + result= -1; else - continue; + { + if (grant_table->cols) + { + List<LEX_COLUMN> columns; + if (replace_column_table(grant_table,tables[3].table, *lex_user, + columns, + grant_table->db, + grant_table->tname, + ~0, 1)) + result= -1; + else + { + revoke= 1; + continue; + } + } + else + { + revoke= 1; + continue; + } + } } + ++counter; } - ++counter; + if (!revoke) + break; } } From e1d5815341cfddde712c271fa3304fc71bd546ea Mon Sep 17 00:00:00 2001 From: "dellis@goetia.(none)" <> Date: Fri, 22 Oct 2004 13:41:40 -0500 Subject: [PATCH 2/2] sql_acl.cc: BUG #5831 Post-review changes, merging improvements from Monty. --- sql/sql_acl.cc | 67 +++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 07647f4eb82..b44b4e9ada5 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3590,7 +3590,7 @@ int mysql_drop_user(THD *thd, List <LEX_USER> &list) int mysql_revoke_all(THD *thd, List <LEX_USER> &list) { - uint counter; + uint counter, revoked; int result; ACL_DB *acl_db; TABLE_LIST tables[4]; @@ -3628,10 +3628,9 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list) as privileges are removed, removal occurs in a repeated loop until no more privileges are revoked. */ - while (1) + do { - int revoke= 0; - for (counter= 0 ; counter < acl_dbs.elements ; ) + for (counter= 0, revoked= 0 ; counter < acl_dbs.elements ; ) { const char *user,*host; @@ -3644,25 +3643,25 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list) if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(system_charset_info, lex_user->host.str, host)) { - if (replace_db_table(tables[1].table, acl_db->db, *lex_user, ~0, 1)) - result= -1; - else + if (!replace_db_table(tables[1].table, acl_db->db, *lex_user, ~0, 1)) { - revoke= 1; + /* + Don't increment counter as replace_db_table deleted the + current element in acl_dbs. + */ + revoked= 1; continue; } + result= -1; // Something went wrong } - ++counter; + counter++; } - if (!revoke) - break; - } + } while (revoked); /* Remove column access */ - while (1) + do { - int revoke= 0; - for (counter= 0 ; counter < column_priv_hash.records ; ) + for (counter= 0, revoked= 0 ; counter < column_priv_hash.records ; ) { const char *user,*host; GRANT_TABLE *grant_table= (GRANT_TABLE*)hash_element(&column_priv_hash, @@ -3679,36 +3678,32 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list) grant_table->db, grant_table->tname, ~0, 0, 1)) + { result= -1; + } else { - if (grant_table->cols) + if (!grant_table->cols) { - List<LEX_COLUMN> columns; - if (replace_column_table(grant_table,tables[3].table, *lex_user, - columns, - grant_table->db, - grant_table->tname, - ~0, 1)) - result= -1; - else - { - revoke= 1; - continue; - } - } - else - { - revoke= 1; + revoked= 1; continue; } + List<LEX_COLUMN> columns; + if (!replace_column_table(grant_table,tables[3].table, *lex_user, + columns, + grant_table->db, + grant_table->tname, + ~0, 1)) + { + revoked= 1; + continue; + } + result= -1; } } - ++counter; + counter++; } - if (!revoke) - break; - } + } while (revoked); } VOID(pthread_mutex_unlock(&acl_cache->lock));