| Bug #73123 | Possible access to freed memory in IS_FREE_LOCK() and IS_USED_LOCK(). | ||
|---|---|---|---|
| Submitted: | 26 Jun 2014 13:24 | Modified: | 24 Sep 2014 1:36 |
| Reporter: | Dmitry Lenev | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: Locking | Severity: | S3 (Non-critical) |
| Version: | 5.5.37-bzr, 5.6.17-bzr | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
[24 Sep 2014 1:36]
Paul DuBois
Noted in 5.5.41, 5.6.22, 5.7.6 changelogs. The IS_FREE_LOCK() and IS_USED_LOCK() function implementations contained a race condition due to which they could access freed memory when a user lock was concurrently checked and freed. Accessing freed memory could result in an incorect function return value or server exit.
[3 Dec 2014 14:29]
Laurynas Biveinis
$ bzr log -r 4714
------------------------------------------------------------
revno: 4714
committer: Praveenkumar Hulakund <praveenkumar.hulakund@oracle.com>
branch nick: mysql-5.5
timestamp: Tue 2014-09-16 11:28:46 +0530
message:
Bug#19070633 - POSSIBLE ACCESS TO FREED MEMORY IN IS_FREE_LOCK()
AND IS_USED_LOCK().
Analysis:
-----------
In functions Item_func_is_free_lock::val_int() and
Item_func_is_used_lock::val_int(), for the specified user lock
name, pointer to its "User_level_lock" object is obtained from hash
"hash_user_locks". Mutex "LOCK_user_locks" is acquired for this
and released immediately. And we are accessing members of
User_level_lock after releasing the mutex. If same user lock is
deleted(released) from concurrent thread then accessing members
results in invalid(freed) memory access issue.
Deleting of user lock is also protected from the mutex
"LOCK_user_locks". Since this mutex is released in "val_int"
functions mentioned above, delete operation proceeds while concurrent
thread tries to access its members.
With the test case, valgrind reports invalid read issues in val_int
functions.
Fix:
-----------
To fix this issue, in "val_int" function of classes
"Item_func_is_free_lock" and "Item_func_is_used_lock", now releasing
mutex "LOCK_user_locks" after accessing User_level_lock members.

Description: Implementations of IS_FREE_LOCK() and IS_USED_LOCK() function contain race condition due to which they can access freed memory in scenario when user-lock being checked is concurrently freed. Accessing to freed memory might result in wrong return value from these functions and occasionally to server crashes. How to repeat: The simplest way is to check the code in sql/item_func.cc: longlong Item_func_is_free_lock::val_int() { ... mysql_mutex_lock(&LOCK_user_locks); ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(), (size_t) res->length()); mysql_mutex_unlock(&LOCK_user_locks); if (!ull || !ull->locked) Note that there is no guarantee that "ull" points to valid/unfreed memory after LOCK_user_locks is unlocked.