From: Shani Peretz <shperetz@nvidia.com>
To: <dev@dpdk.org>
Cc: Shani Peretz <shperetz@nvidia.com>, <stable@dpdk.org>,
Maxime Coquelin <maxime.coquelin@redhat.com>,
Chenbo Xia <chenbox@nvidia.com>,
David Marchand <david.marchand@redhat.com>
Subject: [PATCH] vhost: fix use-after-free race during cleanup
Date: Tue, 4 Nov 2025 10:09:31 +0200 [thread overview]
Message-ID: <20251104080931.8102-1-shperetz@nvidia.com> (raw)
This commit fixes a use-after-free that causes the application
to crash on shutdown (detected by ASAN).
The vhost library uses a background event dispatch thread that monitors
fds with epoll. It runs in an infinite loop, waiting for I/O events
and calling callbacks when they occur.
During cleanup, a race condition existed:
Main Thread: Event Dispatch Thread:
1. Remove fds from fdset while (1) {
2. Close file descriptors epoll_wait() [gets interrupted]
3. Free fdset memory [continues loop]
4. Continue... Accesses fdset... CRASH
}
The main thread would free the fdset memory while the background thread
was still running and using it.
The code had a `destroy` flag that the event dispatch thread checked,
but it was never set during cleanup, and the code never waited for
the thread to actually exit before freeing memory.
This commit implements `fdset_destroy()` that will set the destroy
flag, wait for thread termination, and clean up all resources.
The socket.c is updated to call fdset_destroy() when the last vhost-user
socket is unregistered.
Fixes: 0e38b42bf61c ("vhost: manage FD with epoll")
Cc: stable@dpdk.org
Signed-off-by: Shani Peretz <shperetz@nvidia.com>
---
lib/vhost/fd_man.c | 38 ++++++++++++++++++++++++++++++++++++++
lib/vhost/fd_man.h | 1 +
lib/vhost/socket.c | 7 +++++++
3 files changed, 46 insertions(+)
diff --git a/lib/vhost/fd_man.c b/lib/vhost/fd_man.c
index f9147edee7..ba1b2ead86 100644
--- a/lib/vhost/fd_man.c
+++ b/lib/vhost/fd_man.c
@@ -393,3 +393,41 @@ fdset_event_dispatch(void *arg)
return 0;
}
+
+/**
+ * Destroy the fdset and stop its event dispatch thread.
+ */
+void
+fdset_destroy(struct fdset *pfdset)
+{
+ uint32_t val;
+ int i;
+
+ if (pfdset == NULL)
+ return;
+
+ /* Signal the event dispatch thread to stop */
+ pfdset->destroy = true;
+
+ /* Wait for the event dispatch thread to finish */
+ rte_thread_join(pfdset->tid, &val);
+
+ /* Close the epoll file descriptor */
+ close(pfdset->epfd);
+
+ /* Destroy the mutex */
+ pthread_mutex_destroy(&pfdset->fd_mutex);
+
+ /* Remove from global registry */
+ pthread_mutex_lock(&fdsets_mutex);
+ for (i = 0; i < MAX_FDSETS; i++) {
+ if (fdsets[i] == pfdset) {
+ fdsets[i] = NULL;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&fdsets_mutex);
+
+ /* Free the fdset structure */
+ rte_free(pfdset);
+}
diff --git a/lib/vhost/fd_man.h b/lib/vhost/fd_man.h
index eadcc6fb42..ed2109f3c8 100644
--- a/lib/vhost/fd_man.h
+++ b/lib/vhost/fd_man.h
@@ -21,5 +21,6 @@ int fdset_add(struct fdset *pfdset, int fd,
void fdset_del(struct fdset *pfdset, int fd);
int fdset_try_del(struct fdset *pfdset, int fd);
+void fdset_destroy(struct fdset *pfdset);
#endif
diff --git a/lib/vhost/socket.c b/lib/vhost/socket.c
index 9b4f332f94..0240da8ff0 100644
--- a/lib/vhost/socket.c
+++ b/lib/vhost/socket.c
@@ -1141,6 +1141,13 @@ rte_vhost_driver_unregister(const char *path)
count = --vhost_user.vsocket_cnt;
vhost_user.vsockets[i] = vhost_user.vsockets[count];
vhost_user.vsockets[count] = NULL;
+
+ /* Check if we need to destroy the vhost fdset */
+ if (vhost_user.vsocket_cnt == 0 && vhost_user.fdset != NULL) {
+ fdset_destroy(vhost_user.fdset);
+ vhost_user.fdset = NULL;
+ }
+
pthread_mutex_unlock(&vhost_user.mutex);
return 0;
}
--
2.34.1
next reply other threads:[~2025-11-04 8:10 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-04 8:09 Shani Peretz [this message]
2025-11-04 9:32 ` fengchengwen
2025-11-04 14:31 ` Maxime Coquelin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251104080931.8102-1-shperetz@nvidia.com \
--to=shperetz@nvidia.com \
--cc=chenbox@nvidia.com \
--cc=david.marchand@redhat.com \
--cc=dev@dpdk.org \
--cc=maxime.coquelin@redhat.com \
--cc=stable@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).