<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:\5B8B \4F53 ;
        panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:DengXian;
        panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
        {font-family:"\@\7B49 \7EBF ";
        panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
        {font-family:"\@\5B8B \4F53 ";
        panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        font-size:12.0pt;
        font-family:\5B8B \4F53 ;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 90.0pt 72.0pt 90.0pt;}
div.WordSection1
        {page:WordSection1;}
--></style>
</head>
<body lang="ZH-CN" link="#0563C1" vlink="#954F72" style="word-wrap:break-word">
<div class="WordSection1">
<div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span lang="EN-US" style="font-size:11.0pt">From: Gongming Chen <chengm11@chinatelecom.cn><br>
<br>
When a vhost user message handling error in the event dispatch thread,<br>
vsocket reconn is added to the reconnection list of the reconnection<br>
thread.<br>
Since the reconnection, event dispatching and app configuration thread<br>
do not have common thread protection restrictions, the app config<br>
thread freed vsocket in the rte_vhost_driver_unregister process,<br>
but vsocket reconn can still exist in the reconn_list through this<br>
mechanism.<br>
Then in the reconnection thread, the vsocket is connected again and<br>
conn is added to the dispatch thread.<br>
Finally, the vsocket is accessed again in the event dispatch thread,<br>
resulting in a use-after-free error.<br>
<br>
This patch adds a vhost threads read-write lock to restrict<br>
reconnection, event dispatching and app configuration threads.<br>
When the vhost driver unregisters, it exclusively holds the lock to<br>
safely free the vsocket.<br>
<br>
#0  0x0000000000000025 in ?? ()<br>
#1  0x0000000003ed7ca0 in vhost_user_read_cb at lib/vhost/socket.c:330<br>
#2  0x0000000003ed625f in fdset_event_dispatch at lib/vhost/fd_man.c:283<br>
<br>
Fixes: e623e0c6d8a5 ("vhost: add vhost-user client mode")<br>
Cc: stable@dpdk.org<br>
<br>
Signed-off-by: Gongming Chen <chengm11@chinatelecom.cn><br>
---<br>
 lib/vhost/fd_man.c       |  3 +++<br>
 lib/vhost/meson.build    |  1 +<br>
 lib/vhost/socket.c       | 30 ++++++++++++------------------<br>
 lib/vhost/vhost_thread.c | 33 +++++++++++++++++++++++++++++++++<br>
 lib/vhost/vhost_thread.h | 16 ++++++++++++++++<br>
 5 files changed, 65 insertions(+), 18 deletions(-)<br>
 create mode 100644 lib/vhost/vhost_thread.c<br>
 create mode 100644 lib/vhost/vhost_thread.h<br>
<br>
diff --git a/lib/vhost/fd_man.c b/lib/vhost/fd_man.c<br>
index 481e6b900a..b0e0aa2640 100644<br>
--- a/lib/vhost/fd_man.c<br>
+++ b/lib/vhost/fd_man.c<br>
@@ -9,6 +9,7 @@<br>
 #include <rte_log.h><br>
 <br>
 #include "fd_man.h"<br>
+#include "vhost_thread.h"<br>
 <br>
 RTE_LOG_REGISTER_SUFFIX(vhost_fdset_logtype, fdset, INFO);<br>
 #define RTE_LOGTYPE_VHOST_FDMAN vhost_fdset_logtype<br>
@@ -250,6 +251,7 @@ fdset_event_dispatch(void *arg)<br>
                 if (val < 0)<br>
                         continue;<br>
 <br>
+               vhost_thread_read_lock();<br>
                 need_shrink = 0;<br>
                 for (i = 0; i < numfds; i++) {<br>
                         pthread_mutex_lock(&pfdset->fd_mutex);<br>
@@ -303,6 +305,7 @@ fdset_event_dispatch(void *arg)<br>
 <br>
                 if (need_shrink)<br>
                         fdset_shrink(pfdset);<br>
+               vhost_thread_read_unlock();<br>
         }<br>
 <br>
         return 0;<br>
diff --git a/lib/vhost/meson.build b/lib/vhost/meson.build<br>
index 41b622a9be..7bc1840ed0 100644<br>
--- a/lib/vhost/meson.build<br>
+++ b/lib/vhost/meson.build<br>
@@ -25,6 +25,7 @@ sources = files(<br>
         'vdpa.c',<br>
         'vhost.c',<br>
         'vhost_crypto.c',<br>
+        'vhost_thread.c',<br>
         'vhost_user.c',<br>
         'virtio_net.c',<br>
         'virtio_net_ctrl.c',<br>
diff --git a/lib/vhost/socket.c b/lib/vhost/socket.c<br>
index 96b3ab5595..e05d36f549 100644<br>
--- a/lib/vhost/socket.c<br>
+++ b/lib/vhost/socket.c<br>
@@ -20,6 +20,7 @@<br>
 #include "fd_man.h"<br>
 #include "vduse.h"<br>
 #include "vhost.h"<br>
+#include "vhost_thread.h"<br>
 #include "vhost_user.h"<br>
 <br>
 <br>
@@ -463,6 +464,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)<br>
         struct vhost_user_reconnect *reconn, *next;<br>
 <br>
         while (1) {<br>
+               vhost_thread_read_lock();<br>
                 pthread_mutex_lock(&reconn_list.mutex);<br>
 <br>
                 /*<br>
@@ -494,6 +496,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)<br>
                 }<br>
 <br>
                 pthread_mutex_unlock(&reconn_list.mutex);<br>
+               vhost_thread_read_unlock();<br>
                 sleep(1);<br>
         }<br>
 <br>
@@ -1071,7 +1074,7 @@ rte_vhost_driver_unregister(const char *path)<br>
         if (path == NULL)<br>
                 return -1;<br>
 <br>
-again:<br>
+       vhost_thread_write_lock();<br>
         pthread_mutex_lock(&vhost_user.mutex);<br>
 <br>
         for (i = 0; i < vhost_user.vsocket_cnt; i++) {<br>
@@ -1083,14 +1086,10 @@ rte_vhost_driver_unregister(const char *path)<br>
                         vduse_device_destroy(path);<br>
                 } else if (vsocket->is_server) {<br>
                         /*<br>
-                        * If r/wcb is executing, release vhost_user's<br>
-                        * mutex lock, and try again since the r/wcb<br>
-                        * may use the mutex lock.<br>
+                        * The vhost thread write lock has been acquired,<br>
+                        * and fd must be deleted from fdset.<br>
                          */<br>
-                       if (fdset_try_del(&vhost_user.fdset, vsocket->socket_fd) == -1) {<br>
-                               pthread_mutex_unlock(&vhost_user.mutex);<br>
-                               goto again;<br>
-                       }<br>
+                       fdset_del(&vhost_user.fdset, vsocket->socket_fd);<br>
                 } else if (vsocket->reconnect) {<br>
                         vhost_user_remove_reconnect(vsocket);<br>
                 }<br>
@@ -1102,17 +1101,10 @@ rte_vhost_driver_unregister(const char *path)<br>
                         next = TAILQ_NEXT(conn, next);<br>
 <br>
                         /*<br>
-                        * If r/wcb is executing, release vsocket's<br>
-                        * conn_mutex and vhost_user's mutex locks, and<br>
-                        * try again since the r/wcb may use the<br>
-                        * conn_mutex and mutex locks.<br>
+                        * The vhost thread write lock has been acquired,<br>
+                        * and fd must be deleted from fdset.<br>
                          */<br>
-                       if (fdset_try_del(&vhost_user.fdset,<br>
-                                         conn->connfd) == -1) {<br>
-                               pthread_mutex_unlock(&vsocket->conn_mutex);<br>
-                               pthread_mutex_unlock(&vhost_user.mutex);<br>
-                               goto again;<br>
-                       }<br>
+                       fdset_del(&vhost_user.fdset, conn->connfd);<br>
 <br>
                         VHOST_CONFIG_LOG(path, INFO, "free connfd %d", conn->connfd);<br>
                         close(conn->connfd);<br>
@@ -1134,9 +1126,11 @@ rte_vhost_driver_unregister(const char *path)<br>
                 vhost_user.vsockets[i] = vhost_user.vsockets[count];<br>
                 vhost_user.vsockets[count] = NULL;<br>
                 pthread_mutex_unlock(&vhost_user.mutex);<br>
+               vhost_thread_write_unlock();<br>
                 return 0;<br>
         }<br>
         pthread_mutex_unlock(&vhost_user.mutex);<br>
+       vhost_thread_write_unlock();<br>
 <br>
         return -1;<br>
 }<br>
diff --git a/lib/vhost/vhost_thread.c b/lib/vhost/vhost_thread.c<br>
new file mode 100644<br>
index 0000000000..c7661b745e<br>
--- /dev/null<br>
+++ b/lib/vhost/vhost_thread.c<br>
@@ -0,0 +1,33 @@<br>
+/* SPDX-License-Identifier: BSD-3-Clause<br>
+ * Copyright (c) 2024 China Telecom Cloud Technology Co., Ltd<br>
+ */<br>
+<br>
+#include <rte_rwlock.h><br>
+<br>
+#include "vhost_thread.h"<br>
+<br>
+static rte_rwlock_t vhost_thread_lock = RTE_RWLOCK_INITIALIZER;<br>
+<br>
+void<br>
+vhost_thread_read_lock(void)<br>
+{<br>
+       rte_rwlock_read_lock(&vhost_thread_lock);<br>
+}<br>
+<br>
+void<br>
+vhost_thread_read_unlock(void)<br>
+{<br>
+       rte_rwlock_read_unlock(&vhost_thread_lock);<br>
+}<br>
+<br>
+void<br>
+vhost_thread_write_lock(void)<br>
+{<br>
+       rte_rwlock_write_lock(&vhost_thread_lock);<br>
+}<br>
+<br>
+void<br>
+vhost_thread_write_unlock(void)<br>
+{<br>
+       rte_rwlock_write_unlock(&vhost_thread_lock);<br>
+}<br>
diff --git a/lib/vhost/vhost_thread.h b/lib/vhost/vhost_thread.h<br>
new file mode 100644<br>
index 0000000000..61679172af<br>
--- /dev/null<br>
+++ b/lib/vhost/vhost_thread.h<br>
@@ -0,0 +1,16 @@<br>
+/* SPDX-License-Identifier: BSD-3-Clause<br>
+ * Copyright (c) 2024 China Telecom Cloud Technology Co., Ltd<br>
+ */<br>
+<br>
+#ifndef _VHOST_THREAD_H_<br>
+#define _VHOST_THREAD_H_<br>
+<br>
+void vhost_thread_read_lock(void);<br>
+<br>
+void vhost_thread_read_unlock(void);<br>
+<br>
+void vhost_thread_write_lock(void);<br>
+<br>
+void vhost_thread_write_unlock(void);<br>
+<br>
+#endif<br>
-- <br>
2.32.1 (Apple Git-133)<o:p></o:p></span></p>
</div>
</div>
</body>
</html>