diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-08-03 15:40:13 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-08-03 15:40:13 +0300 |
commit | e6a808bec790fdbbf1dc0a6b03fb6c8b6e41dc01 (patch) | |
tree | 12c275460543a06f4aa07639f62b622a04410813 /storage/innobase/sync | |
parent | be370efac43c26168e13034fa9b0bb0116ca95b4 (diff) | |
download | mariadb-git-e6a808bec790fdbbf1dc0a6b03fb6c8b6e41dc01.tar.gz |
Fix heap-use-after-free in debug code
rw_lock_get_debug_info(): Remove. This function is inherently unsafe
to use, because the copied pointers can become stale between
rw_lock_debug_mutex_exit() and the dereferencing of the pointer in
the caller.
Diffstat (limited to 'storage/innobase/sync')
-rw-r--r-- | storage/innobase/sync/sync0rw.cc | 99 |
1 files changed, 34 insertions, 65 deletions
diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc index c985cf9ee82..0ad646f06b0 100644 --- a/storage/innobase/sync/sync0rw.cc +++ b/storage/innobase/sync/sync0rw.cc @@ -1047,86 +1047,52 @@ rw_lock_own( return(FALSE); } -/** For collecting the debug information for a thread's rw-lock */ -typedef std::vector<rw_lock_debug_t*> Infos; - -/** Get the thread debug info -@param[in] infos The rw-lock mode owned by the threads -@param[in] lock rw-lock to check -@return the thread debug info or NULL if not found */ -void -rw_lock_get_debug_info(const rw_lock_t* lock, Infos* infos) -{ - rw_lock_debug_t* info = NULL; - - ut_ad(rw_lock_validate(lock)); - - rw_lock_debug_mutex_enter(); - - for (info = UT_LIST_GET_FIRST(lock->debug_list); - info != NULL; - info = UT_LIST_GET_NEXT(list, info)) { - - if (os_thread_eq(info->thread_id, os_thread_get_curr_id())) { - - infos->push_back(info); - } - } - - rw_lock_debug_mutex_exit(); -} - /** Checks if the thread has locked the rw-lock in the specified mode, with the pass value == 0. @param[in] lock rw-lock @param[in] flags specify lock types with OR of the rw_lock_flag_t values @return true if locked */ -bool -rw_lock_own_flagged( - const rw_lock_t* lock, - rw_lock_flags_t flags) +bool rw_lock_own_flagged(const rw_lock_t* lock, rw_lock_flags_t flags) { - Infos infos; - - rw_lock_get_debug_info(lock, &infos); - - Infos::const_iterator end = infos.end(); - - for (Infos::const_iterator it = infos.begin(); it != end; ++it) { + ut_ad(rw_lock_validate(lock)); - const rw_lock_debug_t* info = *it; + rw_lock_debug_mutex_enter(); - if (info->pass) { + for (rw_lock_debug_t* info = UT_LIST_GET_FIRST(lock->debug_list); + info != NULL; + info = UT_LIST_GET_NEXT(list, info)) { + if (!os_thread_eq(info->thread_id, os_thread_get_curr_id()) + || info->pass) { continue; } - ut_ad(os_thread_eq(info->thread_id, os_thread_get_curr_id())); - switch (info->lock_type) { case RW_LOCK_S: - - if (flags & RW_LOCK_FLAG_S) { - return(true); + if (!(flags & RW_LOCK_FLAG_S)) { + continue; } break; case RW_LOCK_X: - - if (flags & RW_LOCK_FLAG_X) { - return(true); + if (!(flags & RW_LOCK_FLAG_X)) { + continue; } break; case RW_LOCK_SX: - - if (flags & RW_LOCK_FLAG_SX) { - return(true); + if (!(flags & RW_LOCK_FLAG_SX)) { + continue; } + break; } + + rw_lock_debug_mutex_exit(); + return true; } - return(false); + rw_lock_debug_mutex_exit(); + return false; } /***************************************************************//** @@ -1227,28 +1193,31 @@ rw_lock_t::locked_from() const the same thread can call X lock recursively. */ std::ostringstream msg; - Infos infos; + bool written = false; - rw_lock_get_debug_info(this, &infos); + ut_ad(rw_lock_validate(this)); - ulint i = 0; - Infos::const_iterator end = infos.end(); - - for (Infos::const_iterator it = infos.begin(); it != end; ++it, ++i) { - - const rw_lock_debug_t* info = *it; + rw_lock_debug_mutex_enter(); - ut_ad(os_thread_eq(info->thread_id, os_thread_get_curr_id())); + for (rw_lock_debug_t* info = UT_LIST_GET_FIRST(debug_list); + info != NULL; + info = UT_LIST_GET_NEXT(list, info)) { + if (!os_thread_eq(info->thread_id, os_thread_get_curr_id())) { + continue; + } - if (i > 0) { + if (written) { msg << ", "; } + written = true; + msg << info->file_name << ":" << info->line; } - return(msg.str()); + rw_lock_debug_mutex_exit(); + return(msg.str()); } /** Print the rw-lock information. |