From b52a3b31202b2f0bbc6ab4f1efd1bb814cc7bc2c Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Fri, 15 May 2020 19:10:53 +0300 Subject: [PATCH] Mutex::unlock - decrement _count inside lock `Mutex::unlock` was decrementing the `_count` member after releasing the mutex, which meant it was unprotected, exposing a race that could corrupt the count. This could lead to an assert in `ConditionVariable::wait`, which checks that the mutex count is one. --- rtos/source/Mutex.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rtos/source/Mutex.cpp b/rtos/source/Mutex.cpp index 6860a7884d..460485e08f 100644 --- a/rtos/source/Mutex.cpp +++ b/rtos/source/Mutex.cpp @@ -123,10 +123,12 @@ bool Mutex::trylock_until(Kernel::Clock::time_point abs_time) void Mutex::unlock() { + // Count must be adjusted inside the lock. This would leave it incorrect + // on failure, but it only is used for an assert in ConditionVariable, + // and a mutex release failure means MBED_ERROR anyway. + _count--; + osStatus status = osMutexRelease(_id); - if (osOK == status) { - _count--; - } if (status != osOK && !mbed_get_error_in_progress()) { MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_KERNEL, MBED_ERROR_CODE_MUTEX_UNLOCK_FAILED), "Mutex unlock failed", status);