Skip to content

Commit 9e424b6

Browse files
committed
MENT-1707 Crash at reload_acl_and_cache
The stack function trace for this bug is: libc my_free free_root acl_reload The crash happens because acl_memroot gets corrupted. The issue was that during FLUSH PRIVILEGES we discard the old privileges and create new ones. We have protection in place that no one can accesses the privileges during this time. However one short piece of code called during login of a new user, or change password, was not properly protected, which could in some very rare circumstances case a memory overwrite of a MEMROOT object if at the same time another thread calls FLUSH PRIVILEGES. This it issue is fixed by adding protection around set_user_salt(). I also added asserts to other code that is using the acl_memroot to ensure that it is properly proteced everywhere.
1 parent 18acf97 commit 9e424b6

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

sql/sql_acl.cc

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,7 @@ class User_table_tabular: public User_table
934934

935935
int get_auth(THD *thd, MEM_ROOT *root, ACL_USER *u) const
936936
{
937+
mysql_mutex_assert_owner(&acl_cache->lock);
937938
u->alloc_auth(root, 1);
938939
if (have_password())
939940
{
@@ -2144,6 +2145,9 @@ static bool validate_password(THD *thd, const LEX_CSTRING &user,
21442145
static int set_user_salt(ACL_USER::AUTH *auth, plugin_ref plugin)
21452146
{
21462147
st_mysql_auth *info= (st_mysql_auth *) plugin_decl(plugin)->info;
2148+
2149+
mysql_mutex_assert_owner(&acl_cache->lock);
2150+
21472151
if (info->interface_version >= 0x0202 && info->preprocess_hash &&
21482152
auth->auth_string.length)
21492153
{
@@ -2178,6 +2182,8 @@ static int set_user_auth(THD *thd, const LEX_CSTRING &user,
21782182
plugin_ref plugin= get_auth_plugin(thd, auth->plugin, &unlock_plugin);
21792183
int res= 1;
21802184

2185+
mysql_mutex_assert_owner(&acl_cache->lock);
2186+
21812187
if (!plugin)
21822188
{
21832189
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
@@ -2254,10 +2260,13 @@ static bool set_user_salt_if_needed(ACL_USER *user_copy, int curr_auth,
22542260
if (auth_copy->salt.str)
22552261
return 0; // already done
22562262

2263+
mysql_mutex_lock(&acl_cache->lock);
22572264
if (set_user_salt(auth_copy, plugin))
2265+
{
2266+
mysql_mutex_unlock(&acl_cache->lock);
22582267
return 1;
2268+
}
22592269

2260-
mysql_mutex_lock(&acl_cache->lock);
22612270
ACL_USER *user= find_user_exact(user_copy->host.hostname, user_copy->user.str);
22622271
// make sure the user wasn't altered or dropped meanwhile
22632272
if (user)
@@ -3280,6 +3289,7 @@ ACL_USER::ACL_USER(THD *thd, const LEX_USER &combo,
32803289
const Account_options &options,
32813290
const ulong privileges)
32823291
{
3292+
mysql_mutex_assert_owner(&acl_cache->lock);
32833293
user= safe_lexcstrdup_root(&acl_memroot, combo.user);
32843294
update_hostname(&host, safe_strdup_root(&acl_memroot, combo.host.str));
32853295
hostname_length= combo.host.length;
@@ -3296,6 +3306,8 @@ static int acl_user_update(THD *thd, ACL_USER *acl_user, uint nauth,
32963306
const ulong privileges)
32973307
{
32983308
ACL_USER_PARAM::AUTH *work_copy= NULL;
3309+
mysql_mutex_assert_owner(&acl_cache->lock);
3310+
32993311
if (nauth)
33003312
{
33013313
if (!(work_copy= (ACL_USER_PARAM::AUTH*)
@@ -4971,6 +4983,7 @@ update_role_mapping(LEX_CSTRING *user, LEX_CSTRING *host, LEX_CSTRING *role,
49714983
return 0;
49724984
}
49734985

4986+
mysql_mutex_assert_owner(&acl_cache->lock);
49744987
/* allocate a new entry that will go in the hash */
49754988
ROLE_GRANT_PAIR *hash_entry= new (&acl_memroot) ROLE_GRANT_PAIR;
49764989
if (hash_entry->init(&acl_memroot, user->str, host->str,
@@ -5035,6 +5048,7 @@ replace_proxies_priv_table(THD *thd, TABLE *table, const LEX_USER *user,
50355048

50365049
DBUG_ENTER("replace_proxies_priv_table");
50375050

5051+
mysql_mutex_assert_owner(&acl_cache->lock);
50385052
if (!table)
50395053
{
50405054
my_error(ER_NO_SUCH_TABLE, MYF(0), MYSQL_SCHEMA_NAME.str,

0 commit comments

Comments
 (0)