mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50: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:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -66,6 +66,12 @@ typedef struct esp_event_loop_node {
|
||||
|
||||
typedef SLIST_HEAD(esp_event_loop_nodes, esp_event_loop_node) esp_event_loop_nodes_t;
|
||||
|
||||
typedef struct esp_event_loop_state {
|
||||
portMUX_TYPE lock; /**< spinlock protecting deleting and posts_in_flight */
|
||||
atomic_bool deleting; /**< true when loop deletion has started; read lock-free from ISR */
|
||||
uint32_t posts_in_flight; /**< task-context posts that passed the post-entry gate */
|
||||
} esp_event_loop_state_t;
|
||||
|
||||
/// Event loop
|
||||
typedef struct esp_event_loop_instance {
|
||||
const char* name; /**< name of this event loop */
|
||||
@@ -76,6 +82,7 @@ typedef struct esp_event_loop_instance {
|
||||
SemaphoreHandle_t mutex; /**< mutex for updating the events linked list */
|
||||
esp_event_loop_nodes_t loop_nodes; /**< set of linked lists containing the
|
||||
registered handlers for the loop */
|
||||
esp_event_loop_state_t state; /**< loop deletion and post-entry state */
|
||||
#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING
|
||||
atomic_uint_least32_t events_received; /**< number of events successfully posted to the loop */
|
||||
atomic_uint_least32_t events_dropped; /**< number of events dropped due to queue being full */
|
||||
|
||||
Reference in New Issue
Block a user