From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 302622D9EFF for ; Wed, 20 May 2026 01:21:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=198.175.65.21 ARC-Seal:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779240074; cv=fail; b=ePU35SV/hwU4UY9cK15CBp4seNwLWFmciHJl3+RXbnyszF1+J/oBgePEub8N7w1YtM56Ft2djqaamihLkxhzb9EVFu2rHIDy3w6M6o59iWPGKK2KhpSy6v/VZszAl+idt2fILlj20/Fn79Xoqh3zhleUEwCzh0HxIQZ9cVtrjiw= ARC-Message-Signature:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779240074; c=relaxed/simple; bh=6FGuwkPFj5xizdDffUFZN3wmv+QT7lgKHDeBwhxWkIg=; h=Date:From:To:CC:Subject:Message-ID:References:Content-Type: Content-Disposition:In-Reply-To:MIME-Version; b=mOuaHCgAewMG9tHhmd2qbqWEZjomwDkDJSj7blbaOUtEHTjyx2WFipzaIsbg7a0xAPfgFnUljwMAyayG1z8kFM+ji8gOKEITgS83Oc1frxc+2KNiA3xJZRRRhMd39dRS+BTpB7+EHlzVZY3ODEtBehGwrf6/qnDWpZGWkPb4nK4= ARC-Authentication-Results:i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=fttnBii+; arc=fail smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="fttnBii+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1779240072; x=1810776072; h=date:from:to:cc:subject:message-id:references: in-reply-to:mime-version; bh=6FGuwkPFj5xizdDffUFZN3wmv+QT7lgKHDeBwhxWkIg=; b=fttnBii+OJkprDi8lSlkjYLU2Ww0GPk3/kCJgzv69tC7EyLTjuWEfVWY /Ds6kTfEiPp85kVkn4gEKF/oAo06A2sRT0//WrFc2hw1R4A+BLt5oHp6e sZ3192S58zksTwDuYPFgz+e9ebgZ5QgKJjAutI1Vp+CVNP5tWm7BVEewk xx+jMH6f01ASuuA1N0UKzMuW18aO+AbyDkeqizWzGgWErMvETCzmc3VXg 7AmOoihRnCraWdp0ncdKq/N9mN8Rv0IDYx6UcZXiIo9+al+6uetGFrY87 XqIogEQaoPjyaa3QNXsOzI7m0yrUGqFWT5iDnoh2eJzoZgn2sgZ87E26m A==; X-CSE-ConnectionGUID: SWbRkFNhSI2p3xwhplP2wA== X-CSE-MsgGUID: MUjZTD9LTBmrx1LWe8fkGA== X-IronPort-AV: E=McAfee;i="6800,10657,11791"; a="80033451" X-IronPort-AV: E=Sophos;i="6.23,243,1770624000"; d="scan'208";a="80033451" Received: from fmviesa003.fm.intel.com ([10.60.135.143]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 May 2026 18:21:11 -0700 X-CSE-ConnectionGUID: HKiaVmhSQPiSqxQoR+nnLw== X-CSE-MsgGUID: w7NBXsqLQs2gZ0S2RaXERg== X-ExtLoop1: 1 Received: from fmsmsx902.amr.corp.intel.com ([10.18.126.91]) by fmviesa003.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 May 2026 18:21:10 -0700 Received: from FMSMSX902.amr.corp.intel.com (10.18.126.91) by fmsmsx902.amr.corp.intel.com (10.18.126.91) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.37; Tue, 19 May 2026 18:21:09 -0700 Received: from fmsedg902.ED.cps.intel.com (10.1.192.144) by FMSMSX902.amr.corp.intel.com (10.18.126.91) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.37 via Frontend Transport; Tue, 19 May 2026 18:21:09 -0700 Received: from CO1PR03CU002.outbound.protection.outlook.com (52.101.46.46) by edgegateway.intel.com (192.55.55.82) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.37; Tue, 19 May 2026 18:21:09 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ZXT+cp0zf4dPRC7wMY88TdaFFG04E9SvvZEF96qAFfqh2/t9zXxNmpkCFUq2paTfrJ212nwjv94yWSL/6IwcMrIu04bExh26eEjKW/55/rRCPIHq5/ac4rKCGtvH1otfpDITnpyG+KjvaOsXpW6DWIns1hxd7EO2NmsDYCJ61IPuMyOdIPoGPBHwzpEDhtFN7FRi21xdCNg7LrofvStMP2Uu/UO3J6XhNlwyErJiY0wg+2VGRouwsaX5zHycDQAMmVFqUxgw31LzE60tG552XJlRxlB0fkE2pHjniiBnoHOm93xWK/HgHZwhK4R5TuzHDk2f41wyx0yCpx5MAt9dEQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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=1ZgrJIfkY7/blM4/4JQpxpVTluoG7rr6DBjdQuuVJK0=; b=gEHU9NE07nrmorUD/2d7fHF+deWgNis8qDj0snzLIelhOCaiCwzYug56UOE29YC2rbG8mn5YSpDNDjQMmWwu7ZN4iIisliXJ1oTV4sAwNyTgQWIgX0JDhpH0iAGXxKo5Sajpki5pxUspcGdIf9WKnxLSHLzcZEVyaOrQN1fZijEGKbimvMP5JiuSQfvsW5gZ00tR5pyDFVa0loCTq6L8HGqt8ilH6KjOZK6CT24KAyEghUTmKA/6Xdq8W0eO1wEqOZVQBUB4qRTU9sppc1t8yBvWD2sn7xRV6x+unMU6uE3G1qo7P+9ozfF14HxeCWVN+bJAb0U33KGhRmiuH/pRQA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=intel.com; Received: from SJ1PR11MB6153.namprd11.prod.outlook.com (2603:10b6:a03:488::18) by BL1PR11MB6050.namprd11.prod.outlook.com (2603:10b6:208:392::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.48.14; Wed, 20 May 2026 01:21:06 +0000 Received: from SJ1PR11MB6153.namprd11.prod.outlook.com ([fe80::d6e0:baf2:d31d:c812]) by SJ1PR11MB6153.namprd11.prod.outlook.com ([fe80::d6e0:baf2:d31d:c812%4]) with mapi id 15.21.0025.023; Wed, 20 May 2026 01:21:06 +0000 Date: Wed, 20 May 2026 09:19:52 +0800 From: Fei Li To: Sicong Huang CC: , , , Subject: Re: [PATCH v2 1/1] virt: acrn: Fix irqfd use-after-free during eventfd shutdown Message-ID: References: <20260511135737.2285411-1-congei42@163.com> <20260519112018.2135000-1-congei42@163.com> <20260519112018.2135000-2-congei42@163.com> Content-Type: text/plain; charset="us-ascii" Content-Disposition: inline In-Reply-To: <20260519112018.2135000-2-congei42@163.com> X-ClientProxiedBy: KL1PR02CA0024.apcprd02.prod.outlook.com (2603:1096:820:d::11) To SJ1PR11MB6153.namprd11.prod.outlook.com (2603:10b6:a03:488::18) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SJ1PR11MB6153:EE_|BL1PR11MB6050:EE_ X-MS-Office365-Filtering-Correlation-Id: 884070c3-b604-474a-4770-08deb60e10a7 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|376014|1800799024|42112799006|56012099003|18002099003|22082099003|4143699003|11063799006; X-Microsoft-Antispam-Message-Info: 1UAOzs7g2Lo8LHh9FibGcB2vqohVjdnHxuqFvhI0cnAoSM3fWvNSX4Z6gZCTxWU33UTxxZvljvmGYBhylodWS7Tok1aQ+PhQDE04wR2zGi5HHRVIidkOs4vfJArpNnE6zPs7bEGWHrhqqwyh27G9uHJVLY6dPe3+rr+Pmve5WToYK6fz7Daik4mzilycQaefp2O3G2M/0iFQJE02LBlpqCMgHnOnjrztpfQRkGvlsSAbN+o3eXE2vsKH+DIhQWeFBOFFT74VD0l0p7+7DcF7yZkkiF4n2Zuo0PQriqAgvHwRx8jvwXfMrq196w90OJl23Bjo2i4Q7Vn+hE+ObVeW0MI4R9Pg1FoAatL5YYQVMboaM7xaCbdJ4UvQXYgnaeZBcVhJok/hZsywyujAxAFWMg/8+JZDG8RfjrhHmib+x2c8QqcjKz90W/YMukVIhRYLVPvWRDkXbvbb3PwhFVCwN6QbC94DRi/wgYV95aPVLUohxotHs9pZXB4S/Sh9KJ2jlqGQuKUVmbwI6CCIGwjjFGaA/d/xZDUGLzsz5+0GVO6NPcF59ToFiYrDCZ4jkzxd0bg19P4oCwfTmZppaEV2078v0GuxsNptWv6XZNR9Mb9Q9QOU+4LQdVsLsYBwEIewMe6N00TJK6V6WBNVuI2g6OtVqDMpiDm53B/JfJeJPGPreXFJH68sQVb149cCa7IC X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SJ1PR11MB6153.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(376014)(1800799024)(42112799006)(56012099003)(18002099003)(22082099003)(4143699003)(11063799006);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?wj6V++3ouanyvNkI5l36lPWvbAwEzA0ky/H7uSlmSeZOsyiGSyptpfdjQdku?= =?us-ascii?Q?7miTkalG2b4DP2yeNFCc1ISGUZIJT+Cry3K4AnxhXSN/GEuYgbzPjHYdYTQ9?= =?us-ascii?Q?3Okqy4YpMz5NUyGvjlwdi4gjEs91gOv9P4ldFnaOptJo5+qhSczQ51lqXHDn?= =?us-ascii?Q?68Y5tJMDaRJDvHIIH3vFzF4/dvON86ur9Kiz2bdE8RqaM99JJ0GrabPEaT4q?= =?us-ascii?Q?jMaQDn6YFJZG1MMWXLqvbi88Dko8q7wc3rXfxX7t/Tilwaq++6j605iGYnLT?= =?us-ascii?Q?RoD/UXfkHAdD4MrObPjp5NWH2ZMGpMhXT26OVmlWqcNnjfoUMvocYSEXLXkO?= =?us-ascii?Q?wXDzGz2a0VXb27x48JudVKFHTlAkaszKWqN468cKcfFvY+hLPTJq/JkIwVNL?= =?us-ascii?Q?ktLdDL7doNL2DtwAtNLdbbvSBdwcOs4xvIKWlVIUSj84WbgPog34y+0Bz5cB?= =?us-ascii?Q?i4VsXAoOY9Jw9kbNs/GlpyCvjEhCRQTlNPHsDFTtgcHNGAjt0XAYov3GGXR3?= =?us-ascii?Q?Rur+RqnCyWJzc9prI70a6aOerA9/JKfOAw8KAngAlBjAlz30X0Muv9SFobqx?= =?us-ascii?Q?aXBS/jCOTYL4NUqG2+roJ6mKCIITU5o0I6xWswxH6OaZtmG1MFPdvTWukre6?= =?us-ascii?Q?QIcxqOQDcSzncO0bLmpsuEhdt/WEWx++IMuV5A3/gBukbezQXDpFGFCNczVq?= =?us-ascii?Q?nU79frjZceRHqawiHok5AAee9z91qDdmNrW/azC4FChu+juOX2RjJos6l46T?= =?us-ascii?Q?9hAMRE7AAamWhUCZ7LCTwtTY3fvZ6v1rXa+WHSBJrNgtxJssKX7Bm8KiKvaK?= =?us-ascii?Q?5WMpKNQBTQ/DRovdbSa0QRi3ikHxHnuG+2pso1V/L/8QTBPCI7DHgalFgCn/?= =?us-ascii?Q?NvJnf3X3pDWBAdbULXD12wIg02NpOa4vCnrDOD8OAZ9KmSO9DtBGTxI3J65i?= =?us-ascii?Q?yfN4cHS2m0EfZ+fD8G+v/YZ81o/NVpgFbAG0HuPrZXwmhBbCA7iWwuLaZk2y?= =?us-ascii?Q?cFoKwh4H8nF/13FPrukerJxnxN1lLH2fGDBEXwWU/a6oCHYsuyT3F3DT5but?= =?us-ascii?Q?7mlZVsyo/QUbN9oT5idNYLH9o3YpibImAyLXR0g9QMOj9B+KHQYs2EdNXUCm?= =?us-ascii?Q?JM/8/06c2ZzyXSWlfe0ZC4WiNXp2RYLNnoSX8ES6L/nVf9u9v8Pdrbcy3gkR?= =?us-ascii?Q?IzCdUaCeXZaH40s1B1RpUSMwBN3YMX14T1jAj+xfCYSWj50ByUbYz8StfF8S?= =?us-ascii?Q?yGZfsSGKobDGZeRlLBeKIUG3KRmzcgWentL3qQ1/uc0wo2ACDpMepk+icQJr?= =?us-ascii?Q?/u2S5mVigUCgW2nfio/Rr3Eqkhd2o99n9AOlbobR3DLGuWEmdJ+pH46fuRFz?= =?us-ascii?Q?SZtnDJBM8tVL7bUctKD7AE05Rr1WmGeftnMADhTEhcN3mHNAS36HUjEN967R?= =?us-ascii?Q?5+fmLa0ydOagBBu6HS+Cp0oat3cmiyRZGqkMvPSh2ZGcp6fC6ChKDy8qBX4z?= =?us-ascii?Q?mEi+/iDza1SS9k7blQiJaPdXX0IIj6gPMT88fVsECi3mSTLHsWp46V+QeX8T?= =?us-ascii?Q?9KtaJ/ta2tmf8sVqjF7naLVA0iVZNd7jzfYE7Z7ahSt4I5X78wbsgImdwVIS?= =?us-ascii?Q?F+HuDwMFotVYAq060I9hvqXnpHq9x7sAwp838lFDbleuPI2WvYUF1P/9IA6d?= =?us-ascii?Q?Gt0dOvdq1ecrdUNZNgbucyoS3HuSRCYBW8V5OLI+sdrW1Yv9ytMt3hRgBSoz?= =?us-ascii?Q?P4eBaMV1Zg=3D=3D?= X-Exchange-RoutingPolicyChecked: i8b2TpvgDVGs/jbqWB2C733Izp6RY9Bw7+kR5G7GhLspqV+uHN9TC+tIG6hWA9i8nRq+JwAttXDWyvPiIJwMyZh/Kg339V8rKvyaSL1BFmGExCRzW7wPSdVzMYzn+G1SL/Rzb3yBqqtMrGxa4bnvKNp/b4LHjkAxC0/gUlGSCVWgEYbQvcLPjROMVPi81HbA3IyNQgXm+C5l2kQhRBQJGrIKTk2JX7zBaC1Yi9QQ9L+bztUhL3kbItXDc4ZqwzhPMg8yFlCjWmVHOapQUGOkWHosXL/PSb0mryY8kfMeL586oMcm8Kc5WCm1iovbOY0VeCRuoj1AH/Br2tvZerf/3A== X-MS-Exchange-CrossTenant-Network-Message-Id: 884070c3-b604-474a-4770-08deb60e10a7 X-MS-Exchange-CrossTenant-AuthSource: SJ1PR11MB6153.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 May 2026 01:21:06.1517 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: Z88XxAre2bON2dz0uaHixBFxV5lwUOP0HdxcFMVWc2JZ1078Nvh27nvxnOh9BO/zXUjlfXYX2v3yoP8BrxAaug== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL1PR11MB6050 X-OriginatorOrg: intel.com On 2026-05-19 at 19:20:18 +0800, Sicong Huang wrote: > acrn_irqfd_deassign() and the eventfd EPOLLHUP wakeup can race and free > the same struct hsm_irqfd: > > CPU0 CPU1 > ---- ---- > eventfd_release() > wake_up_poll(EPOLLHUP) > hsm_irqfd_wakeup() > queue_work(&irqfd->shutdown) > acrn_irqfd_deassign() > hsm_irqfd_shutdown() > list_del_init() > eventfd_ctx_remove_wait_queue() > eventfd_ctx_put() > kfree(irqfd) > hsm_irqfd_shutdown_work() > container_of(work, ..., shutdown) > irqfd->vm <-- use-after-free > > The deassign path freed the irqfd while a shutdown work item was > already queued by EPOLLHUP (or vice versa), so the work item could > resurrect a dangling pointer through container_of(). > > Switch to the lifetime model used by KVM irqfds: > > - Deassign/deinit only deactivate the irqfd: remove it from vm->irqfds > under irqfds_lock and queue the cleanup work. > - hsm_irqfd_shutdown_work() becomes the sole owner that unhooks the > eventfd waitqueue entry, drops the eventfd reference and frees the > irqfd. > - A new HSM_IRQFD_FLAG_SHUTDOWN bit guarded by test_and_set_bit() > ensures the cleanup work is queued at most once, no matter how many > of {EPOLLHUP, deassign, deinit} fire concurrently. This is safe to > call from the waitqueue callback, which runs with wqh->lock held and > IRQs disabled and therefore cannot take irqfds_lock. > - acrn_irqfd_deassign() flushes vm->irqfd_wq before returning so the > eventfd is fully detached on return. acrn_irqfd_deinit() deactivates > every irqfd, flushes the workqueue and only then destroys it, so no > path can queue_work() onto a torn-down workqueue. > - acrn_irqfd_assign() now installs the eventfd waitqueue entry and > publishes the irqfd to vm->irqfds under irqfds_lock, so the irqfd is > never visible to deassign/deinit before its waitqueue entry is in > place, and any EPOLLHUP that fires in the assign window queues > cleanup work that blocks on irqfds_lock until publication is done. > > Signed-off-by: Sicong Huang Hi Sicong, Thanks, v2 looks much better to me. Reviewed-by: Fei Li > --- > drivers/virt/acrn/irqfd.c | 71 ++++++++++++++++++++++++--------------- > 1 file changed, 44 insertions(+), 27 deletions(-) > > diff --git a/drivers/virt/acrn/irqfd.c b/drivers/virt/acrn/irqfd.c > index acf8cd5f8f8c..feeba7eda494 100644 > --- a/drivers/virt/acrn/irqfd.c > +++ b/drivers/virt/acrn/irqfd.c > @@ -16,6 +16,9 @@ > > #include "acrn_drv.h" > > +/* Cleanup work has been queued; set via test_and_set_bit(). */ > +#define HSM_IRQFD_FLAG_SHUTDOWN 0 > + > /** > * struct hsm_irqfd - Properties of HSM irqfd > * @vm: Associated VM pointer > @@ -25,6 +28,7 @@ > * @list: Entry within &acrn_vm.irqfds of irqfds of a VM > * @pt: Structure for select/poll on the associated eventfd > * @msi: MSI data > + * @flags: Internal lifecycle flags (HSM_IRQFD_FLAG_*) > */ > struct hsm_irqfd { > struct acrn_vm *vm; > @@ -34,6 +38,7 @@ struct hsm_irqfd { > struct list_head list; > poll_table pt; > struct acrn_msi_entry msi; > + unsigned long flags; > }; > > static void acrn_irqfd_inject(struct hsm_irqfd *irqfd) > @@ -44,30 +49,29 @@ static void acrn_irqfd_inject(struct hsm_irqfd *irqfd) > irqfd->msi.msi_data); > } > > -static void hsm_irqfd_shutdown(struct hsm_irqfd *irqfd) > +/* Queue the cleanup work at most once. Safe from atomic context. */ > +static void hsm_irqfd_queue_shutdown(struct hsm_irqfd *irqfd) > { > - u64 cnt; > - > - lockdep_assert_held(&irqfd->vm->irqfds_lock); > - > - /* remove from wait queue */ > - list_del_init(&irqfd->list); > - eventfd_ctx_remove_wait_queue(irqfd->eventfd, &irqfd->wait, &cnt); > - eventfd_ctx_put(irqfd->eventfd); > - kfree(irqfd); > + if (!test_and_set_bit(HSM_IRQFD_FLAG_SHUTDOWN, &irqfd->flags)) > + queue_work(irqfd->vm->irqfd_wq, &irqfd->shutdown); > } > > +/* Sole owner of @irqfd: unhook waitqueue, drop eventfd ref, free. */ > static void hsm_irqfd_shutdown_work(struct work_struct *work) > { > - struct hsm_irqfd *irqfd; > - struct acrn_vm *vm; > + struct hsm_irqfd *irqfd = container_of(work, struct hsm_irqfd, > + shutdown); > + struct acrn_vm *vm = irqfd->vm; > + u64 cnt; > > - irqfd = container_of(work, struct hsm_irqfd, shutdown); > - vm = irqfd->vm; > mutex_lock(&vm->irqfds_lock); > if (!list_empty(&irqfd->list)) > - hsm_irqfd_shutdown(irqfd); > + list_del_init(&irqfd->list); > mutex_unlock(&vm->irqfds_lock); > + > + eventfd_ctx_remove_wait_queue(irqfd->eventfd, &irqfd->wait, &cnt); > + eventfd_ctx_put(irqfd->eventfd); > + kfree(irqfd); > } > > /* Called with wqh->lock held and interrupts disabled */ > @@ -76,17 +80,16 @@ static int hsm_irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, > { > unsigned long poll_bits = (unsigned long)key; > struct hsm_irqfd *irqfd; > - struct acrn_vm *vm; > > irqfd = container_of(wait, struct hsm_irqfd, wait); > - vm = irqfd->vm; > + > if (poll_bits & POLLIN) > /* An event has been signaled, inject an interrupt */ > acrn_irqfd_inject(irqfd); > > if (poll_bits & POLLHUP) > - /* Do shutdown work in thread to hold wqh->lock */ > - queue_work(vm->irqfd_wq, &irqfd->shutdown); > + /* Defer teardown to the cleanup work; can't sleep here. */ > + hsm_irqfd_queue_shutdown(irqfd); > > return 0; > } > @@ -142,6 +145,12 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args) > init_waitqueue_func_entry(&irqfd->wait, hsm_irqfd_wakeup); > init_poll_funcptr(&irqfd->pt, hsm_irqfd_poll_func); > > + /* > + * Hold irqfds_lock across waitqueue install and list_add so the > + * irqfd is not visible to deassign/deinit before its waitqueue > + * entry is in place, and any racing EPOLLHUP cleanup work blocks > + * on irqfds_lock until publication completes. > + */ > mutex_lock(&vm->irqfds_lock); > list_for_each_entry(tmp, &vm->irqfds, list) { > if (irqfd->eventfd != tmp->eventfd) > @@ -150,14 +159,12 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args) > mutex_unlock(&vm->irqfds_lock); > goto fail; > } > - list_add_tail(&irqfd->list, &vm->irqfds); > - mutex_unlock(&vm->irqfds_lock); > > - /* Check the pending event in this stage */ > events = vfs_poll(fd_file(f), &irqfd->pt); > - > + list_add_tail(&irqfd->list, &vm->irqfds); > if (events & EPOLLIN) > acrn_irqfd_inject(irqfd); > + mutex_unlock(&vm->irqfds_lock); > > return 0; > fail: > @@ -180,13 +187,17 @@ static int acrn_irqfd_deassign(struct acrn_vm *vm, > mutex_lock(&vm->irqfds_lock); > list_for_each_entry_safe(irqfd, tmp, &vm->irqfds, list) { > if (irqfd->eventfd == eventfd) { > - hsm_irqfd_shutdown(irqfd); > + list_del_init(&irqfd->list); > + hsm_irqfd_queue_shutdown(irqfd); > break; > } > } > mutex_unlock(&vm->irqfds_lock); > eventfd_ctx_put(eventfd); > > + /* Wait for cleanup work to finish so the eventfd is fully detached. */ > + flush_workqueue(vm->irqfd_wq); > + > return 0; > } > > @@ -219,9 +230,15 @@ void acrn_irqfd_deinit(struct acrn_vm *vm) > struct hsm_irqfd *irqfd, *next; > > dev_dbg(acrn_dev.this_device, "VM %u irqfd deinit.\n", vm->vmid); > - destroy_workqueue(vm->irqfd_wq); > + > mutex_lock(&vm->irqfds_lock); > - list_for_each_entry_safe(irqfd, next, &vm->irqfds, list) > - hsm_irqfd_shutdown(irqfd); > + list_for_each_entry_safe(irqfd, next, &vm->irqfds, list) { > + list_del_init(&irqfd->list); > + hsm_irqfd_queue_shutdown(irqfd); > + } > mutex_unlock(&vm->irqfds_lock); > + > + /* Drain all cleanup work before tearing the workqueue down. */ > + flush_workqueue(vm->irqfd_wq); > + destroy_workqueue(vm->irqfd_wq); > } > -- > 2.34.1 >