Skip to content

Commit a1a8d7b

Browse files
Bug#24452241: ASAN PROBLEMS/SIGNAL 11 WITH INNODB.INNODB_MYSQL
Description: A race condition in acl_get() can cause memory leak and/or corruption. Fix is to acquire proper locks before modifying global datastructure.
1 parent 49ae5b7 commit a1a8d7b

File tree

1 file changed

+42
-11
lines changed

1 file changed

+42
-11
lines changed

sql/auth/sql_auth_cache.cc

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,12 +1021,38 @@ static const uchar* check_get_key(const uchar *arg, size_t *length)
10211021

10221022
void clear_and_init_db_cache()
10231023
{
1024-
if (my_hash_inited(&db_cache))
1025-
my_hash_free(&db_cache);
1024+
my_hash_reset(&db_cache);
1025+
}
10261026

1027-
(void)my_hash_init(&db_cache, &my_charset_utf8_bin,
1028-
0, 0, get_grant_db, my_free,
1029-
0, key_memory_acl_cache);
1027+
1028+
/**
1029+
Insert a new entry in db_cache
1030+
1031+
@param thd [in] Handle to THD object
1032+
@param entry [in] Entry to be inserted in db_cache
1033+
*/
1034+
1035+
static void
1036+
insert_entry_in_db_cache(THD *thd, acl_entry *entry)
1037+
{
1038+
DBUG_ENTER("insert_entry_in_db_cache");
1039+
/* Either have WRITE lock or none at all */
1040+
DBUG_ASSERT(assert_acl_cache_write_lock(thd) ||
1041+
!assert_acl_cache_read_lock(thd));
1042+
1043+
Acl_cache_lock_guard acl_cache_lock(thd, Acl_cache_lock_mode::WRITE_MODE);
1044+
1045+
/*
1046+
In following cases release memory and return
1047+
1. Could not lock cache : This is ok because db_cache
1048+
second level cache anyways.
1049+
2. my_hash_insert returned error. This is likely because
1050+
someone already inserted a similar entry.
1051+
*/
1052+
if (!acl_cache_lock.lock(false) ||
1053+
my_hash_insert(&db_cache, (uchar *)entry))
1054+
my_free(entry);
1055+
DBUG_VOID_RETURN;
10301056
}
10311057

10321058

@@ -1117,7 +1143,8 @@ ulong acl_get(THD *thd, const char *host, const char *ip,
11171143
entry->access=(db_access & host_access);
11181144
entry->length=key_length;
11191145
memcpy((uchar*) entry->key,key,key_length);
1120-
my_hash_insert(&db_cache, (uchar *) entry);
1146+
acl_cache_lock.unlock();
1147+
insert_entry_in_db_cache(thd, entry);
11211148
}
11221149
DBUG_PRINT("exit", ("access: 0x%lx", db_access & host_access));
11231150
DBUG_RETURN(db_access & host_access);
@@ -1465,10 +1492,14 @@ my_bool acl_init(bool dont_read_acl_tables)
14651492
my_bool return_val;
14661493
DBUG_ENTER("acl_init");
14671494

1468-
acl_cache_initialized= true;
14691495
#ifndef NO_EMBEDDED_ACCESS_CHECKS
14701496
init_acl_cache();
1497+
1498+
(void)my_hash_init(&db_cache, &my_charset_utf8_bin,
1499+
0, 0, get_grant_db, my_free,
1500+
0, key_memory_acl_cache);
14711501
#endif
1502+
acl_cache_initialized= true;
14721503

14731504
/*
14741505
cache built-in native authentication plugins,
@@ -2113,17 +2144,17 @@ void acl_free(bool end)
21132144
delete acl_proxy_users;
21142145
acl_proxy_users= NULL;
21152146
my_hash_free(&acl_check_hosts);
2116-
if (end)
2147+
if (!end)
2148+
clear_and_init_db_cache();
2149+
else
21172150
{
2118-
if (acl_cache_initialized)
2151+
if (acl_cache_initialized == true)
21192152
{
21202153
my_hash_free(&db_cache);
21212154
plugin_unlock(0, native_password_plugin);
21222155
acl_cache_initialized= false;
21232156
}
21242157
}
2125-
else
2126-
clear_and_init_db_cache();
21272158
}
21282159

21292160

0 commit comments

Comments
 (0)