mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
fix(esp_event): prevent UAF race between post and loop delete (SEC-222)
esp_event_post_to() could access loop->queue / loop->mutex after esp_event_loop_delete() freed them when both ran concurrently. Introduce esp_event_loop_state_t with: - posts_in_flight: reference-count incremented atomically (under state.lock spinlock) before touching any loop resources, decremented on every exit path via goto on_err. - deleting: atomic_bool set by esp_event_loop_delete() to block new posts from entering the critical section. esp_event_loop_delete() sets deleting=true, then busy-waits (releasing and re-acquiring loop->mutex each tick) until posts_in_flight reaches zero before proceeding with teardown. esp_event_isr_post_to() performs a lock-free atomic_load of deleting as a best-effort guard; ISR context cannot participate in the spinlock protocol but the window is documented and accepted.
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
extern "C" {
|
||||
#include "Mocktask.h"
|
||||
#include "Mockqueue.h"
|
||||
#include "Mockportmacro.h"
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -102,6 +103,8 @@ TEST_CASE("test esp_event_loop_create no_task(void)")
|
||||
xQueueTakeMutexRecursive_IgnoreAndReturn(0);
|
||||
xQueueGiveMutexRecursive_IgnoreAndReturn(0);
|
||||
xQueueReceive_IgnoreAndReturn(0);
|
||||
vPortEnterCritical_Ignore();
|
||||
vPortExitCritical_Ignore();
|
||||
esp_event_loop_handle_t loop = nullptr;
|
||||
|
||||
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
||||
@@ -115,6 +118,8 @@ TEST_CASE("test esp_event_loop_create no_task(void)")
|
||||
xQueueReceive_StopIgnore();
|
||||
xQueueTakeMutexRecursive_StopIgnore();
|
||||
xQueueGiveMutexRecursive_StopIgnore();
|
||||
vPortEnterCritical_StopIgnore();
|
||||
vPortExitCritical_StopIgnore();
|
||||
}
|
||||
|
||||
TEST_CASE("test esp_event_loop_create with_task(void)")
|
||||
@@ -125,6 +130,8 @@ TEST_CASE("test esp_event_loop_create with_task(void)")
|
||||
xQueueTakeMutexRecursive_IgnoreAndReturn(0);
|
||||
xQueueGiveMutexRecursive_IgnoreAndReturn(0);
|
||||
xQueueReceive_IgnoreAndReturn(0);
|
||||
vPortEnterCritical_Ignore();
|
||||
vPortExitCritical_Ignore();
|
||||
esp_event_loop_handle_t loop = nullptr;
|
||||
|
||||
esp_event_loop_args_t loop_args = test_event_get_default_loop_args();
|
||||
@@ -138,6 +145,8 @@ TEST_CASE("test esp_event_loop_create with_task(void)")
|
||||
xQueueReceive_StopIgnore();
|
||||
xQueueTakeMutexRecursive_StopIgnore();
|
||||
xQueueGiveMutexRecursive_StopIgnore();
|
||||
vPortEnterCritical_StopIgnore();
|
||||
vPortExitCritical_StopIgnore();
|
||||
}
|
||||
|
||||
TEST_CASE("registering with ANY_BASE but specific ID fails")
|
||||
|
||||
Reference in New Issue
Block a user