mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
1) loop->mutex is created with xSemaphoreCreateRecursiveMutex(). FreeRTOS requires that recursive mutexes are only acquired and released with xSemaphoreTakeRecursive / xSemaphoreGiveRecursive. esp_event_handler_unregister_with_internal() used the non-recursive xSemaphoreTake(loop->mutex, 0) / xSemaphoreGive(loop->mutex) in the fast path. The non-recursive Take bypasses uxRecursiveCallCount bookkeeping; if the same task subsequently takes the mutex recursively (e.g. re-entry from a handler or a follow-up register), the call count drifts. The non-recursive Give then unconditionally drops the holder, allowing another task to acquire the mutex while the original task still believes it holds the lock — a full lock violation on the handler list leading to UAF and potential RCE on attacker-driven event floods. Fix: replace xSemaphoreTake/xSemaphoreGive with the Recursive variants in the fast (try-take with timeout 0) path of unregister_with_internal. 2) avoid use-after-free when unregistering handler from a callback The recursive try-lock introduced in SEC-220 succeeds re-entrantly when a handler unregisters itself from within its own callback, causing the handler node to be freed immediately while the dispatch loop still writes profiling counters to it after the callback returns. Route the in-callback case to the deferred cleanup path and only free directly once no dispatch is active. Closes SEC_220