From f974099b4272725f76dc55a0126bedaaba40af8d Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 6 May 2022 14:40:12 +0200 Subject: [PATCH] vfs: Fix potential select() race if both sock and other-fd trigger This fixes a potential race condition in select() if both a socket-fd and non-socket fd trigger simultaneously to unblock this select. In case of both fds, we use lwip's local thread semaphore, so we only have to try return it (if it was taken/triggered more than once) when we exit select(). Closes https://github.com/espressif/esp-idf/issues/8896 --- components/vfs/vfs.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index fc5e08f6b0..b433c98693 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -1053,8 +1053,16 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds if (ret >= 0) { ret += set_global_fd_sets(vfs_fds_triple, vfs_count, readfds, writefds, errorfds); } - if (sel_sem.is_sem_local && sel_sem.sem) { - vSemaphoreDelete(sel_sem.sem); + if (sel_sem.sem) { // Cleanup the select semaphore + if (sel_sem.is_sem_local) { + vSemaphoreDelete(sel_sem.sem); + } else if (socket_select) { + SemaphoreHandle_t *s = sel_sem.sem; + /* Select might have been triggered from both lwip and vfs fds at the same time, and + * we have to make sure that the lwip semaphore is cleared when we exit select(). + * It is safe, as the semaphore belongs to the calling thread. */ + xSemaphoreTake(*s, 0); + } sel_sem.sem = NULL; } _lock_acquire(&s_fd_table_lock);