From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 8F13A43DD9; Wed, 3 Apr 2024 04:57:23 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 350C940144; Wed, 3 Apr 2024 04:57:23 +0200 (CEST) Received: from TYVP286CU001.outbound.protection.outlook.com (mail-japaneastazolkn19010001.outbound.protection.outlook.com [52.103.43.1]) by mails.dpdk.org (Postfix) with ESMTP id 0B1D6400D7; Wed, 3 Apr 2024 04:57:21 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=VSZHcvk4qX2plpHZ8EKHInNJckc4P0jwVLtqkW7ATJBo4CpXnKaBOPoqGWCnyyoA1XHD4XwNc6Vzou+FGo/YJjCW9qCtQlcrAR8lKJC522xoo4DtWzv+eyASxdo0qnv5sMKmygj+fd6HbO3dAgsnns1ZPd08ZJPw8yRZgDepr3wKX0n/0m/OoDot4cDZtGhvEQFrCCi7gdtdcrikX26fEaQlbTHk/hrymAhOnKWRooidr66FcPkhEhMf83+IuMRVlNCW2FWNZJgxGhXVL8WFOJelzjrugRRf4aD1W79iLmsnR25xbV7q7rey2pBx2I8UZj7dcF801NNWu9Peywi+3A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=4cN0s20wvoW/kr5+2RxBN+yd+DriL3h0+X8zjOzzLRY=; b=D2lL2dSTIwfrxJ2/ibC6cW1Wx6Aa9M0aDVdOXWihJgxiqYMM3rJJ43Qz1ED0/KeY4VdO5Qw9nj216Jznevlvsf8O3jInsdcmqBFNaNtaYIRJtDQEW1cX1kg2dYJ0mYoJPfeZBjqSIO8aQudN2dIzz2teOxnLeRw5Yz0ePtBUHqXMZ1KGq2p79wGhERU3CupYdOQs1RVSmSq8tVefnQ9kcbHSwES3YpXkmLX0sHWdsl1YKNChLUIccwnloH2Vw55l+YOFwTUUbxrKabdttc9GmAgA8jSc7p31ri9KgxsNIsvTYQ+5D/5/vvFY/GOos02QbV9j6E+FJwyzFdD2ILImIA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=outlook.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=4cN0s20wvoW/kr5+2RxBN+yd+DriL3h0+X8zjOzzLRY=; b=cyt6E2jYWh/ZZRk1AKFpBhxmEwYbANxjovgFq6fX5YpI50FULfOwkkYyj8pN/AqhVVfWpvuJWcEWyuOKLBwg8WNwfdS6DCa2eXqiaamgAtjL7uf6UUebTVvfF4C7x1KS4Vq3SKHHrhoyDTzFLMtKIAgI/vaGuZ8vF5geiq7h2K0HyfCydf9VinaU1ealTj3nUEEyuYo5w7qSbbKQLOkAsQx/3GgkVEVs/p3qrYJQm2kCXqCgPPJlHgoKbN22232CNWvKVObsYlkoDJ3Zkg/jL/u2iJ911BaFP8OaJTVO/NIvwF3dg/WpJ3MGgyZqEVKjBflmIA6NYupraLl+W9E9iw== Received: from TYAP286MB0649.JPNP286.PROD.OUTLOOK.COM (2603:1096:402:38::13) by OSZP286MB1799.JPNP286.PROD.OUTLOOK.COM (2603:1096:604:1bc::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7409.46; Wed, 3 Apr 2024 02:57:18 +0000 Received: from TYAP286MB0649.JPNP286.PROD.OUTLOOK.COM ([fe80::3b2d:34ba:11e6:b203]) by TYAP286MB0649.JPNP286.PROD.OUTLOOK.COM ([fe80::3b2d:34ba:11e6:b203%4]) with mapi id 15.20.7409.042; Wed, 3 Apr 2024 02:57:18 +0000 From: Gongming Chen To: "maxime.coquelin@redhat.com" , "chenbox@nvidia.com" CC: "dev@dpdk.org" , Gongming Chen , "stable@dpdk.org" Subject: [PATCH] vhost: fix crash caused by accessing a freed vsocket Thread-Topic: [PATCH] vhost: fix crash caused by accessing a freed vsocket Thread-Index: AQHahN+F+HV3UmLxxECApksGTpoAyLFV2snH Date: Wed, 3 Apr 2024 02:57:18 +0000 Message-ID: References: <20240402092402.43452-1-chengongming1900@outlook.com> In-Reply-To: <20240402092402.43452-1-chengongming1900@outlook.com> Accept-Language: zh-CN, en-US Content-Language: zh-CN X-MS-Has-Attach: X-MS-TNEF-Correlator: x-tmn: [kLCMODZiBg6SbbpZfQFMvN2n7cqOrfQY] x-ms-publictraffictype: Email x-ms-traffictypediagnostic: TYAP286MB0649:EE_|OSZP286MB1799:EE_ x-ms-office365-filtering-correlation-id: 9913d6be-2b57-4747-ed30-08dc5389c64e x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: +/CYhTlksOs7+sCt5K/xOPZ/ry2P4C+DxuaP/shxDqfCeNVooxmrdm6+WnpPFmD54PoJwrKYa3D31YfeQW9+WTpwoZ/A0BuRN+/vbImfgLq2Mq8QbMhx5vNeSJCs7tmi3YY2I7h8WGlHk+shSR1+k70bVkp0RTe3/CtD722g9uN7ujel3VII7JvWbjBHMi5q1O9haWnwtd6SBJ+SU0Lux5/KNwN/iAtfvGbroajvYco5L4alV5Cb/BYZj1s71daYNeFmnNZwyUofJT/z5iBoBXHeHHEpVjhc6XPLGLazYUZQwcMaDJULPi/zo3cWqzLpa2F9r08xOakRQmm4xy7ALNNQBT6vfAcwBr5wr9a3dFT9zxmJQO2/iYNOZ+lOmzN741xZYBNNyTXFfKiqwlDnVZht+76+DNWT+JfSxzwFQxqJEMSlMPO15HIclk25I87J6uKCuk7Vwb4lFnVh0s92k1cv6R5EUPCLkkMtdTbe2zOyjHK5bEv+LiD/as6q+9QxXS4vgXcKAHuPKgOAYUn2JGGSwy1J+kpSpCku0okfr1fNq8LGHU9ku3IwOUmXb/Il x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?qWeGQM75yTYiOmgd2sXNP/mbNQyBzuozFNgqPGN+f/IWXopJxwLjzsjOn32p?= =?us-ascii?Q?jVIharjOuyOv57WddS39pKklBYEjfp/jPCunngH5cJfu5NzQlwGnn5nP6ib8?= =?us-ascii?Q?UkdlXHtBXV8azDgnH74lGU/6zf9KiY05HNt7afi7fITtY4h3kr88GqUlKmvu?= =?us-ascii?Q?uVReJnj5OFBTHueUcBjA8HMY/sLseejJmiRGefF9lqiQjdTz4HhTaiCXiag6?= =?us-ascii?Q?euKeqveHx6ebc5mWkjQ8ZN1Q1HN9LfGKyhTfh3H2aUWMxV1OhE7tZYSmNsbd?= =?us-ascii?Q?hs8NFQJY4+DQxpCobTwU3uAXkpfw83gHQA3H3/u+LSPaZHHiCzuW+UpJYHHQ?= =?us-ascii?Q?r6Ym6vut6bjpNybZsUwpKkxKpFNrBX3HunePOnkm2oVYOXxFfWtqKcxIeVHh?= =?us-ascii?Q?wFsywa43m00ROegJD1C+wSjA18dR6tvFcdc8HJxZjJC4S7Mvh8lezZLnLP/O?= =?us-ascii?Q?Itm+pMkT/cglvV/DGZuvwQcAtcT1PTAsSujtOjMYKS5v27OcHu1z/PtatEhU?= =?us-ascii?Q?/WTBDRykafD4EYne97FXOadlI5Bv+3Mt8fIrobOKjf/AqmECxUHkp8Tgz4qx?= =?us-ascii?Q?NibLSX2Zumw09G9zOj8xHxmm3RHqjeppUQM0sZpkc2GzLuCVCNxqB2fp+mxC?= =?us-ascii?Q?7K2wQ2R3FNbYDtQ0lvCcGWSIA/CtuR7WgugQrJxk85NCg7/prhMSckEH8AXd?= =?us-ascii?Q?I1m4axq+GP+hRX6vekmbyCxdZSF1tP5gf5vrPg1z0gh26xRwTR6Dieexoz9u?= =?us-ascii?Q?9+QdnkCbnL8dTBhXuEa7+NxG4YX+1X4WMLkeTvsSBDU8XDTH7sQSoiuJ+GD5?= =?us-ascii?Q?e04AAdcyG2XBTjKNrRzt3dGbSzAwUcJqqJQ8lQqJ608bsvTC2A4X5cZ3IF4m?= =?us-ascii?Q?HM9zGmMnrr06BEHfHH0J1+sg9sW38lyUTJc0IhmTUKK+1lnRNv2uvXquGOZY?= =?us-ascii?Q?E/D6mGqq0hzyetd3V6qolKSNFQQnkCfpP7qzq0j/eGTHnfK6IE4pp5qUqGyq?= =?us-ascii?Q?uk4Yf7uXJaGBzfCwKFyGN974VogApkcW8utwupMC1tASFBKsZawLG+hQONk5?= =?us-ascii?Q?XPwF6SH72EE+6CRe3IEuBM8Yk+LRnYDK/jI3UXhM7dXyc5A43m5Aqy0LFek4?= =?us-ascii?Q?0nqRIvoCqOQLLptm62bMKc2ZyLOgzqR/NhlUk+hdNyUI7pZN2+AgskMnVE7/?= =?us-ascii?Q?MmF3otFfMq/4mxcfdhQUY5Cr5aZQ6aGCyn76cNgoO4H/XpoTsJDI+98UPMML?= =?us-ascii?Q?eN7Qpdq27xoTaINgaKFkx+0K88JnhP3Thbzk9BDQ2Q=3D=3D?= Content-Type: multipart/alternative; boundary="_000_TYAP286MB0649588660B26F0CC783BAABD83D2TYAP286MB0649JPNP_" MIME-Version: 1.0 X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: TYAP286MB0649.JPNP286.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-CrossTenant-Network-Message-Id: 9913d6be-2b57-4747-ed30-08dc5389c64e X-MS-Exchange-CrossTenant-originalarrivaltime: 03 Apr 2024 02:57:18.1982 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-rms-persistedconsumerorg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: OSZP286MB1799 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org --_000_TYAP286MB0649588660B26F0CC783BAABD83D2TYAP286MB0649JPNP_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable From: Gongming Chen When a vhost user message handling error in the event dispatch thread, vsocket reconn is added to the reconnection list of the reconnection thread. Since the reconnection, event dispatching and app configuration thread do not have common thread protection restrictions, the app config thread freed vsocket in the rte_vhost_driver_unregister process, but vsocket reconn can still exist in the reconn_list through this mechanism. Then in the reconnection thread, the vsocket is connected again and conn is added to the dispatch thread. Finally, the vsocket is accessed again in the event dispatch thread, resulting in a use-after-free error. This patch adds a vhost threads read-write lock to restrict reconnection, event dispatching and app configuration threads. When the vhost driver unregisters, it exclusively holds the lock to safely free the vsocket. #0 0x0000000000000025 in ?? () #1 0x0000000003ed7ca0 in vhost_user_read_cb at lib/vhost/socket.c:330 #2 0x0000000003ed625f in fdset_event_dispatch at lib/vhost/fd_man.c:283 Fixes: e623e0c6d8a5 ("vhost: add vhost-user client mode") Cc: stable@dpdk.org Signed-off-by: Gongming Chen --- lib/vhost/fd_man.c | 3 +++ lib/vhost/meson.build | 1 + lib/vhost/socket.c | 30 ++++++++++++------------------ lib/vhost/vhost_thread.c | 33 +++++++++++++++++++++++++++++++++ lib/vhost/vhost_thread.h | 16 ++++++++++++++++ 5 files changed, 65 insertions(+), 18 deletions(-) create mode 100644 lib/vhost/vhost_thread.c create mode 100644 lib/vhost/vhost_thread.h diff --git a/lib/vhost/fd_man.c b/lib/vhost/fd_man.c index 481e6b900a..b0e0aa2640 100644 --- a/lib/vhost/fd_man.c +++ b/lib/vhost/fd_man.c @@ -9,6 +9,7 @@ #include #include "fd_man.h" +#include "vhost_thread.h" RTE_LOG_REGISTER_SUFFIX(vhost_fdset_logtype, fdset, INFO); #define RTE_LOGTYPE_VHOST_FDMAN vhost_fdset_logtype @@ -250,6 +251,7 @@ fdset_event_dispatch(void *arg) if (val < 0) continue; + vhost_thread_read_lock(); need_shrink =3D 0; for (i =3D 0; i < numfds; i++) { pthread_mutex_lock(&pfdset->fd_mutex); @@ -303,6 +305,7 @@ fdset_event_dispatch(void *arg) if (need_shrink) fdset_shrink(pfdset); + vhost_thread_read_unlock(); } return 0; diff --git a/lib/vhost/meson.build b/lib/vhost/meson.build index 41b622a9be..7bc1840ed0 100644 --- a/lib/vhost/meson.build +++ b/lib/vhost/meson.build @@ -25,6 +25,7 @@ sources =3D files( 'vdpa.c', 'vhost.c', 'vhost_crypto.c', + 'vhost_thread.c', 'vhost_user.c', 'virtio_net.c', 'virtio_net_ctrl.c', diff --git a/lib/vhost/socket.c b/lib/vhost/socket.c index 96b3ab5595..e05d36f549 100644 --- a/lib/vhost/socket.c +++ b/lib/vhost/socket.c @@ -20,6 +20,7 @@ #include "fd_man.h" #include "vduse.h" #include "vhost.h" +#include "vhost_thread.h" #include "vhost_user.h" @@ -463,6 +464,7 @@ vhost_user_client_reconnect(void *arg __rte_unused) struct vhost_user_reconnect *reconn, *next; while (1) { + vhost_thread_read_lock(); pthread_mutex_lock(&reconn_list.mutex); /* @@ -494,6 +496,7 @@ vhost_user_client_reconnect(void *arg __rte_unused) } pthread_mutex_unlock(&reconn_list.mutex); + vhost_thread_read_unlock(); sleep(1); } @@ -1071,7 +1074,7 @@ rte_vhost_driver_unregister(const char *path) if (path =3D=3D NULL) return -1; -again: + vhost_thread_write_lock(); pthread_mutex_lock(&vhost_user.mutex); for (i =3D 0; i < vhost_user.vsocket_cnt; i++) { @@ -1083,14 +1086,10 @@ rte_vhost_driver_unregister(const char *path) vduse_device_destroy(path); } else if (vsocket->is_server) { /* - * If r/wcb is executing, release vhost_user's - * mutex lock, and try again since the r/wcb - * may use the mutex lock. + * The vhost thread write lock has been acquired, + * and fd must be deleted from fdset. */ - if (fdset_try_del(&vhost_user.fdset, vsocket->socke= t_fd) =3D=3D -1) { - pthread_mutex_unlock(&vhost_user.mutex); - goto again; - } + fdset_del(&vhost_user.fdset, vsocket->socket_fd); } else if (vsocket->reconnect) { vhost_user_remove_reconnect(vsocket); } @@ -1102,17 +1101,10 @@ rte_vhost_driver_unregister(const char *path) next =3D TAILQ_NEXT(conn, next); /* - * If r/wcb is executing, release vsocket's - * conn_mutex and vhost_user's mutex locks, and - * try again since the r/wcb may use the - * conn_mutex and mutex locks. + * The vhost thread write lock has been acquired, + * and fd must be deleted from fdset. */ - if (fdset_try_del(&vhost_user.fdset, - conn->connfd) =3D=3D -1) { - pthread_mutex_unlock(&vsocket->conn_mutex); - pthread_mutex_unlock(&vhost_user.mutex); - goto again; - } + fdset_del(&vhost_user.fdset, conn->connfd); VHOST_CONFIG_LOG(path, INFO, "free connfd %d", con= n->connfd); close(conn->connfd); @@ -1134,9 +1126,11 @@ rte_vhost_driver_unregister(const char *path) vhost_user.vsockets[i] =3D vhost_user.vsockets[count]; vhost_user.vsockets[count] =3D NULL; pthread_mutex_unlock(&vhost_user.mutex); + vhost_thread_write_unlock(); return 0; } pthread_mutex_unlock(&vhost_user.mutex); + vhost_thread_write_unlock(); return -1; } diff --git a/lib/vhost/vhost_thread.c b/lib/vhost/vhost_thread.c new file mode 100644 index 0000000000..c7661b745e --- /dev/null +++ b/lib/vhost/vhost_thread.c @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2024 China Telecom Cloud Technology Co., Ltd + */ + +#include + +#include "vhost_thread.h" + +static rte_rwlock_t vhost_thread_lock =3D RTE_RWLOCK_INITIALIZER; + +void +vhost_thread_read_lock(void) +{ + rte_rwlock_read_lock(&vhost_thread_lock); +} + +void +vhost_thread_read_unlock(void) +{ + rte_rwlock_read_unlock(&vhost_thread_lock); +} + +void +vhost_thread_write_lock(void) +{ + rte_rwlock_write_lock(&vhost_thread_lock); +} + +void +vhost_thread_write_unlock(void) +{ + rte_rwlock_write_unlock(&vhost_thread_lock); +} diff --git a/lib/vhost/vhost_thread.h b/lib/vhost/vhost_thread.h new file mode 100644 index 0000000000..61679172af --- /dev/null +++ b/lib/vhost/vhost_thread.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2024 China Telecom Cloud Technology Co., Ltd + */ + +#ifndef _VHOST_THREAD_H_ +#define _VHOST_THREAD_H_ + +void vhost_thread_read_lock(void); + +void vhost_thread_read_unlock(void); + +void vhost_thread_write_lock(void); + +void vhost_thread_write_unlock(void); + +#endif -- 2.32.1 (Apple Git-133) --_000_TYAP286MB0649588660B26F0CC783BAABD83D2TYAP286MB0649JPNP_ Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable

From: Gongming Chen <chengm11@chinatelecom.cn= >

When a vhost user message handling error in the event dispatch thread,
vsocket reconn is added to the reconnection list of the reconnection
thread.
Since the reconnection, event dispatching and app configuration thread
do not have common thread protection restrictions, the app config
thread freed vsocket in the rte_vhost_driver_unregister process,
but vsocket reconn can still exist in the reconn_list through this
mechanism.
Then in the reconnection thread, the vsocket is connected again and
conn is added to the dispatch thread.
Finally, the vsocket is accessed again in the event dispatch thread,
resulting in a use-after-free error.

This patch adds a vhost threads read-write lock to restrict
reconnection, event dispatching and app configuration threads.
When the vhost driver unregisters, it exclusively holds the lock to
safely free the vsocket.

#0  0x0000000000000025 in ?? ()
#1  0x0000000003ed7ca0 in vhost_user_read_cb at lib/vhost/socket.c:330=
#2  0x0000000003ed625f in fdset_event_dispatch at lib/vhost/fd_man.c:2= 83

Fixes: e623e0c6d8a5 ("vhost: add vhost-user client mode")
Cc: stable@dpdk.org

Signed-off-by: Gongming Chen <chengm11@chinatelecom.cn>
---
 lib/vhost/fd_man.c       |  3 +++<= br>  lib/vhost/meson.build    |  1 +
 lib/vhost/socket.c       | 30 +++++++++= +++------------------
 lib/vhost/vhost_thread.c | 33 +++++++++++++++++++++++++++++++++
 lib/vhost/vhost_thread.h | 16 ++++++++++++++++
 5 files changed, 65 insertions(+), 18 deletions(-)
 create mode 100644 lib/vhost/vhost_thread.c
 create mode 100644 lib/vhost/vhost_thread.h

diff --git a/lib/vhost/fd_man.c b/lib/vhost/fd_man.c
index 481e6b900a..b0e0aa2640 100644
--- a/lib/vhost/fd_man.c
+++ b/lib/vhost/fd_man.c
@@ -9,6 +9,7 @@
 #include <rte_log.h>
 
 #include "fd_man.h"
+#include "vhost_thread.h"
 
 RTE_LOG_REGISTER_SUFFIX(vhost_fdset_logtype, fdset, INFO);
 #define RTE_LOGTYPE_VHOST_FDMAN vhost_fdset_logtype
@@ -250,6 +251,7 @@ fdset_event_dispatch(void *arg)
            &nb= sp;    if (val < 0)
            &nb= sp;            conti= nue;
 
+            &n= bsp;  vhost_thread_read_lock();
            &nb= sp;    need_shrink =3D 0;
            &nb= sp;    for (i =3D 0; i < numfds; i++) {
            &nb= sp;            pthre= ad_mutex_lock(&pfdset->fd_mutex);
@@ -303,6 +305,7 @@ fdset_event_dispatch(void *arg)
 
            &nb= sp;    if (need_shrink)
            &nb= sp;            fdset= _shrink(pfdset);
+            &n= bsp;  vhost_thread_read_unlock();
         }
 
         return 0;
diff --git a/lib/vhost/meson.build b/lib/vhost/meson.build
index 41b622a9be..7bc1840ed0 100644
--- a/lib/vhost/meson.build
+++ b/lib/vhost/meson.build
@@ -25,6 +25,7 @@ sources =3D files(
         'vdpa.c',
         'vhost.c',
         'vhost_crypto.c',
+        'vhost_thread.c',
         'vhost_user.c',
         'virtio_net.c',
         'virtio_net_ctrl.c',
diff --git a/lib/vhost/socket.c b/lib/vhost/socket.c
index 96b3ab5595..e05d36f549 100644
--- a/lib/vhost/socket.c
+++ b/lib/vhost/socket.c
@@ -20,6 +20,7 @@
 #include "fd_man.h"
 #include "vduse.h"
 #include "vhost.h"
+#include "vhost_thread.h"
 #include "vhost_user.h"
 
 
@@ -463,6 +464,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
         struct vhost_user_reconnec= t *reconn, *next;
 
         while (1) {
+            &n= bsp;  vhost_thread_read_lock();
            &nb= sp;    pthread_mutex_lock(&reconn_list.mutex);
 
            &nb= sp;    /*
@@ -494,6 +496,7 @@ vhost_user_client_reconnect(void *arg __rte_unused)
            &nb= sp;    }
 
            &nb= sp;    pthread_mutex_unlock(&reconn_list.mutex);
+            &n= bsp;  vhost_thread_read_unlock();
            &nb= sp;    sleep(1);
         }
 
@@ -1071,7 +1074,7 @@ rte_vhost_driver_unregister(const char *path)
         if (path =3D=3D NULL)
            &nb= sp;    return -1;
 
-again:
+       vhost_thread_write_lock();
         pthread_mutex_lock(&vh= ost_user.mutex);
 
         for (i =3D 0; i < vhost= _user.vsocket_cnt; i++) {
@@ -1083,14 +1086,10 @@ rte_vhost_driver_unregister(const char *path)
            &nb= sp;            vduse= _device_destroy(path);
            &nb= sp;    } else if (vsocket->is_server) {
            &nb= sp;            /* -            &n= bsp;           * If r/wcb= is executing, release vhost_user's
-            &n= bsp;           * mutex lo= ck, and try again since the r/wcb
-            &n= bsp;           * may use = the mutex lock.
+            &n= bsp;           * The vhos= t thread write lock has been acquired,
+            &n= bsp;           * and fd m= ust be deleted from fdset.
            &nb= sp;            = */
-            &n= bsp;          if (fdset_try_de= l(&vhost_user.fdset, vsocket->socket_fd) =3D=3D -1) {
-            &n= bsp;            = ;      pthread_mutex_unlock(&vhost_user.mutex)= ;
-            &n= bsp;            = ;      goto again;
-            &n= bsp;          }
+            &n= bsp;          fdset_del(&v= host_user.fdset, vsocket->socket_fd);
            &nb= sp;    } else if (vsocket->reconnect) {
            &nb= sp;            vhost= _user_remove_reconnect(vsocket);
            &nb= sp;    }
@@ -1102,17 +1101,10 @@ rte_vhost_driver_unregister(const char *path)
            &nb= sp;            next = =3D TAILQ_NEXT(conn, next);
 
            &nb= sp;            /* -            &n= bsp;           * If r/wcb= is executing, release vsocket's
-            &n= bsp;           * conn_mut= ex and vhost_user's mutex locks, and
-            &n= bsp;           * try agai= n since the r/wcb may use the
-            &n= bsp;           * conn_mut= ex and mutex locks.
+            &n= bsp;           * The vhos= t thread write lock has been acquired,
+            &n= bsp;           * and fd m= ust be deleted from fdset.
            &nb= sp;            = */
-            &n= bsp;          if (fdset_try_de= l(&vhost_user.fdset,
-            &n= bsp;            = ;            &n= bsp;   conn->connfd) =3D=3D -1) {
-            &n= bsp;            = ;      pthread_mutex_unlock(&vsocket->conn_= mutex);
-            &n= bsp;            = ;      pthread_mutex_unlock(&vhost_user.mutex)= ;
-            &n= bsp;            = ;      goto again;
-            &n= bsp;          }
+            &n= bsp;          fdset_del(&v= host_user.fdset, conn->connfd);
 
            &nb= sp;            VHOST= _CONFIG_LOG(path, INFO, "free connfd %d", conn->connfd);
            &nb= sp;            close= (conn->connfd);
@@ -1134,9 +1126,11 @@ rte_vhost_driver_unregister(const char *path)
            &nb= sp;    vhost_user.vsockets[i] =3D vhost_user.vsockets[count]= ;
            &nb= sp;    vhost_user.vsockets[count] =3D NULL;
            &nb= sp;    pthread_mutex_unlock(&vhost_user.mutex);
+            &n= bsp;  vhost_thread_write_unlock();
            &nb= sp;    return 0;
         }
         pthread_mutex_unlock(&= vhost_user.mutex);
+       vhost_thread_write_unlock();
 
         return -1;
 }
diff --git a/lib/vhost/vhost_thread.c b/lib/vhost/vhost_thread.c
new file mode 100644
index 0000000000..c7661b745e
--- /dev/null
+++ b/lib/vhost/vhost_thread.c
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2024 China Telecom Cloud Technology Co., Ltd
+ */
+
+#include <rte_rwlock.h>
+
+#include "vhost_thread.h"
+
+static rte_rwlock_t vhost_thread_lock =3D RTE_RWLOCK_INITIALIZER;
+
+void
+vhost_thread_read_lock(void)
+{
+       rte_rwlock_read_lock(&vhost_threa= d_lock);
+}
+
+void
+vhost_thread_read_unlock(void)
+{
+       rte_rwlock_read_unlock(&vhost_thr= ead_lock);
+}
+
+void
+vhost_thread_write_lock(void)
+{
+       rte_rwlock_write_lock(&vhost_thre= ad_lock);
+}
+
+void
+vhost_thread_write_unlock(void)
+{
+       rte_rwlock_write_unlock(&vhost_th= read_lock);
+}
diff --git a/lib/vhost/vhost_thread.h b/lib/vhost/vhost_thread.h
new file mode 100644
index 0000000000..61679172af
--- /dev/null
+++ b/lib/vhost/vhost_thread.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2024 China Telecom Cloud Technology Co., Ltd
+ */
+
+#ifndef _VHOST_THREAD_H_
+#define _VHOST_THREAD_H_
+
+void vhost_thread_read_lock(void);
+
+void vhost_thread_read_unlock(void);
+
+void vhost_thread_write_lock(void);
+
+void vhost_thread_write_unlock(void);
+
+#endif
--
2.32.1 (Apple Git-133)

--_000_TYAP286MB0649588660B26F0CC783BAABD83D2TYAP286MB0649JPNP_--