From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <010701a15a3a31ac-44f48c59-f930-4e24-a55a-ec817090149e-000000@eu-central-1.amazonses.com> Received: from AM0PR83CU005.outbound.protection.outlook.com (mail-westeuropeazon11020129.outbound.protection.outlook.com [52.101.69.129]) by lore.virtuozzo.com (Postfix) with ESMTPS id 9190E8045D for ; Tue, 20 Oct 2026 16:52:11 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=EV87n4XSiMa/p6abdBowYJYf9NgrTeSRrkB7hiqMQ/oougY0OzXaJkeHLsyrxR3BDhcEzecET5GPceoco/rwlXV/7nHUSjlIDfEEGZ4KVwFQx73jbinjKhu2yj4px4J9LnPeivVnQDhkHMbtL4KegcxDfwnMcaUleoc2uyB2VIRjVNqmllwdOcMdkPuIXeUtFJFhujymz9pKw7ietuggsYbMZhp/GMtuP1rl/iw11wX9PfZ3hCJBAZOdthzfLDe3vjGwfbkCxYe0v0+wxJO9vpA7sIISfXBuZngXouJyUWn8xyDPLlkorYVNlpDMeOvGY0TnMvv0xpGk4CIxVc6Zuw== 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=Vn2MU8S9AKOyueSd9hDsLxlo50dx3bUVwVkujTcA6eI=; b=Zi3m88DjknJ/uKdHRlO+HzYSRfH6VPRUsdMWpRnPSiy/SrRrLmFtgzMsD4QA68DlfNfAc31lPyu/+43r2tfPcTvf2sNQ59UVcBVBwsm+EnNWs5DW2vGwmTIakAfjybR/Fu09kv3BSMsohrtUAXHJ/yzRyi7qatm3EoIzOQbblbF0LVspEXGkjofvOIoPdoMFgWkaS/7vdd8N5A6GylyUyGjuw1uIT45nS3uWsO8AzZ2Os93/smwxNYBWdP3nerQcs4vDuFHPf8lGWefVTR9cnXIQTngnomqKChupHfyPFJncwnhDZ3SSRSYPagELCFV99mvC1YO3TSj9uVmWJoaf0w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 69.169.224.5) smtp.rcpttodomain=virtuozzo.com smtp.mailfrom=eu-central-1.amazonses.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=sashiko.virtuozzo.com; dkim=pass (signature was verified) header.d=sashiko.virtuozzo.com; dkim=pass (signature was verified) header.d=amazonses.com; arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=virtuozzo.onmicrosoft.com; s=selector2-virtuozzo-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Vn2MU8S9AKOyueSd9hDsLxlo50dx3bUVwVkujTcA6eI=; b=CES/oWhVUNSNQrPbZfboBuNniVANfoy40QxxBKEEGJOv7TaKr8oS9r9ATGOrNSAZSwq1KtxWQhe40EeIXHpCbe9yrlGDGey44hp9q0aGxrvp1gisg/jQHS59cddMC2Cz2f2ITcA30cIHpFIFxanjJC4VyNhnEAX/kCScurl+CjM= Received: from AS4P192CA0012.EURP192.PROD.OUTLOOK.COM (2603:10a6:20b:5da::20) by GV2PR08MB11563.eurprd08.prod.outlook.com (2603:10a6:150:2cf::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.546.14; Tue, 20 Oct 2026 16:52:06 +0000 Received: from AMS1EPF00000090.eurprd05.prod.outlook.com (2603:10a6:20b:5da:cafe::90) by AS4P192CA0012.outlook.office365.com (2603:10a6:20b:5da::20) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.522.19 via Frontend Transport; Tue, 20 Oct 2026 16:52:06 +0000 Authentication-Results: mx.microsoft.com 1; spf=pass (sender IP is 69.169.224.5) smtp.mailfrom=eu-central-1.amazonses.com; dkim=pass (signature was verified) header.d=sashiko.virtuozzo.com;dkim=pass (signature was verified) header.d=amazonses.com;dmarc=pass action=none header.from=sashiko.virtuozzo.com; Received-SPF: Pass (protection.outlook.com: domain of eu-central-1.amazonses.com designates 69.169.224.5 as permitted sender) receiver=protection.outlook.com; client-ip=69.169.224.5; helo=b224-5.smtp-out.eu-central-1.amazonses.com; pr=C Received: from b224-5.smtp-out.eu-central-1.amazonses.com (69.169.224.5) by AMS1EPF00000090.mail.protection.outlook.com (10.167.242.87) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.546.15 via Frontend Transport; Tue, 20 Oct 2026 16:52:06 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=23yjbh4k34hwzfubhuiim7m4inbd3ick; d=sashiko.virtuozzo.com; t=1792515125; h=Message-ID:From:Subject:To:In-Reply-To:References:Content-Type:Content-Transfer-Encoding:Date; bh=14x5t8K4njE2mSWztElxx9iSgFyd2O/wYhH1hNu4j2E=; b=Wn3Ev2DLEvOX+/mKaWasCb4c8wb2jDfxyesjlYeBcyH7YF+HZzyaGR9QGJZvD8jx rY3eSqoUoxjbMq04fCI+QP/YsYVqje6bDczUSCga5AWPZoHaOFVHzFqSUrpd3iqprV+ +rBfoy7Wf+pbGXuR0io32UdBokgLR/EjCCgOcgVCiWbkkm+wPeqvXTOfPaeSFgJL8ao /uHA9t0KVm4T2Gkjl7O1VyM0tnZdo8Zj9NeiV4jV8QbmyXMxG4tDIyHRRnRn7cgUQVA HomELDikw9b2V2Ms/RhvbI+YHwlJq1edXjqtARp0+VdzCpDqgEg+ENQGSLm7ZKzxV8K o91zzDYh6Q== DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=qftdzk2dqsatjnlrq4r5brjbihpfcrsh; d=amazonses.com; t=1792515125; h=Message-ID:From:Subject:To:In-Reply-To:References:Content-Type:Content-Transfer-Encoding:Date:Feedback-ID; bh=14x5t8K4njE2mSWztElxx9iSgFyd2O/wYhH1hNu4j2E=; b=odYFlYqb6XNY339d/gdtlxiTpsVx/z62D+F8u9g3J20F1TiDRa9x0Qod1Bammu6e CpgJbN10qa5O2FqN7lEK9X+f4j2X+rjL4LEhkIMoNjUbK9jLw5mAeTTGQlq7C2z8Tcc f37iNf/I+OXqG3afQCxU2vyfqDSy0t+whwl3o7hg= Message-ID: <010701a15a3a31ac-44f48c59-f930-4e24-a55a-ec817090149e-000000@eu-central-1.amazonses.com> From: no-reply@sashiko.virtuozzo.com Subject: Re: [PATCH QEMU HCI-8.1 v4 20/31] kvm: tolerate ioctls after kvm_close() To: Andrey Drobyshev , svt-core@virtuozzo.com In-Reply-To: <20261020-vfio_v1-v4-20-83a5668230e5@virtuozzo.com> References: <20261020-vfio_v1-v4-0-83a5668230e5@virtuozzo.com> <20261020-vfio_v1-v4-20-83a5668230e5@virtuozzo.com> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Date: Tue, 20 Oct 2026 16:52:05 +0000 Feedback-ID: ::1.eu-central-1.2wRQJBpg9g1fGRYexx3dUuYGS25Bux+2TEOx72/m6U4=:AmazonSES X-SES-Outgoing: 2026.10.20-69.169.224.5 X-EOPAttributedMessage: 0 X-EOPTenantAttributedMessage: 0bc7f26d-0264-416e-a6fc-8352af79c58f:0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: AMS1EPF00000090:EE_|GV2PR08MB11563:EE_ MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: e947d3e0-c737-4ca1-a7a6-08df2eca7933 X-LD-Processed: 0bc7f26d-0264-416e-a6fc-8352af79c58f,ExtAddr X-MS-Exchange-AtpMessageProperties: SA List-Id: svt-core@virtuozzo.com X-MS-Exchange-Transport-Rules-Loop: 1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|704161411799003|9140799003|32142699015|376014|48200799018|61400799027|6133799003|5113699003|4113699003|55112099003|18002099003|22082099003|16102099003|10067099003|13003099007|3023799007|4143699003|261009223027099003|56012099006|5063699009; X-Microsoft-Antispam-Message-Info: gPXchA6Y6kom3RzWDNT0pg92KRkbrdtmCXg18u+tfk+8u7cKQvs/31+lfA4xruHnrtVpPy6jLtpbVmodrKGYbk9Xai81QEwXA0XMf2Zep8P3K+CtlMNyhXoBhG2JLBSx9nZS9wnOI493u/2ukabJQuql8UYoJDfOLQ4gelm4FUagmszt4pSDgGRCyZ7eLQriiFMCxRdemin3hhjkJ6zs8H+dMilYen8gMLTW/b4KveqRcnN+H405RoTkxewWcnYs8N+WlAyWr4W8MizcIBp8QKBSW8POCwsz0rY6LSbPcEgcWBPwm/3QSZ94zqVqLlGZ5ZCogF1o5LZSdEtLUaIlCTzqrqLQQfWG13IP59pVQeft5/7I00o4LwS7C8yC1DzYsw8tFiE6Whru3xuQS8e5TANhagzTqN1583zjzWCrkfie7Zke+QxfsA/dNxufMQl5rxr/W+DnCOIlZWacKOCf8M/R83XUhpavoYSdj0fu1Cfm9zyzJncQEDDStmCUvoRZuTwo+6afMf5AOFNBwOkphlLKjWqYlGR3LQ3q7JBaFqg0kZgubMZyX9XcdrLMePKp6rrGuh3+muhCo9gOE2NzgsZryngzTI23YLjaa9+qTaV/yMRPPgCvECIxcTjAH3Vdy5Ml47Wt0IEW2dQy79NGa3+Un84nFLUAlxG0XM9XpKy3h5GucyIdx0Yrgxcy+T67uMOVUKnFIscPl7esDe/79OnQTj84wnKBgSCvDVwQqMwCvmZFALjggF0T8GiEgc9FoJsp9U3svRvU4CcVwj+HivDiejHqa3yCIQwAAsc708HvcCaXOyLOg+gxv1RWGdkr52Z4S/ESxnKTiIRyjtWIYA== X-Forefront-Antispam-Report: CIP:69.169.224.5;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:b224-5.smtp-out.eu-central-1.amazonses.com;PTR:b224-5.smtp-out.eu-central-1.amazonses.com;CAT:NONE;SFS:(13230040)(704161411799003)(9140799003)(32142699015)(376014)(48200799018)(61400799027)(6133799003)(5113699003)(4113699003)(55112099003)(18002099003)(22082099003)(16102099003)(10067099003)(13003099007)(3023799007)(4143699003)(261009223027099003)(56012099006)(5063699009);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: RWsB0/CdO9iT7PT14xxOfFnC44gX92OI5kzz3l5Ytzzig2iKO0e1+clJrvS/AobU0jMXBgyzKQbtPUd5ZlaDJiU7N0epgVnAgjNs5H3rjhfCUw13xl9PUZSin55zGFvNsCfmzELUsgB0u0Bifj8B6hYinYAJvy9oCLxhutfc0Rf6MnzLVPCpX8Qmzp6hTOZr4KVCZYNTONQtMPyIU2k6cZujX7B+ogply60tII+QAXLhMEskKVcNkY95ndK3VD2tsjdwJHa65AE7fDPYUsNxY8JGUIWvpWLmQ9uzectG4mbfgAb22rSfvZVyjcsYjUe4sqPalu3htJE+vgznIlOlDcfXomrbiYMD1ZTvXAG02LHKzbrrWQUdnW8bno2MEnBrfIhcbT27ZfzUSp6eRWAksIhwNX236h8nOSpNuIzY98CXBnjhtg3PnDeSbOsOuERW X-ExternalRecipientOutboundConnectors: 0bc7f26d-0264-416e-a6fc-8352af79c58f X-OriginatorOrg: virtuozzo.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Oct 2026 16:52:06.0979 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: e947d3e0-c737-4ca1-a7a6-08df2eca7933 X-MS-Exchange-CrossTenant-Id: 0bc7f26d-0264-416e-a6fc-8352af79c58f X-MS-Exchange-CrossTenant-AuthSource: AMS1EPF00000090.eurprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: Internet X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV2PR08MB11563 Thank you for your contribution! Sashiko AI review found 4 potential issue(= s) to consider: - [Medium] kvm: fake 0 return from kvm_vm_ioctl() after kvm_close() is take= n as a valid fd - [Low] kvm: kvm_vm_ioctl() fake success leaves kvm_set_irq() reading unini= t event.status - [Low] kvm: kvm_close() sentinel checks in ioctl wrappers are not synchron= ized with non-BQL callers - [Low] kvm: ioctl wrappers return 0 for every ioctl after kvm_close(), fak= ing success -- commit 09dbc4fd8a681d8276f3d8eda8630fee15bf5809 Author: Andrey Drobyshev kvm: tolerate ioctls after kvm_close() This patch keeps kvm_state allocated after kvm_close() and makes kvm_ioctl(), kvm_vm_ioctl() and kvm_vcpu_ioctl() return 0 once the descriptors have been closed. The aim is to stop a retired cpr-transfer source from crashing on a late interrupt, such as the MSI-X delivery triggered by net_cleanup(). > diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c > --- a/accel/kvm/kvm-all.c > +++ b/accel/kvm/kvm-all.c [ ... ] > @@ -644,7 +644,6 @@ void kvm_close(void) > close(kvm_state->fd); > kvm_state->fd =3D -1; > } > - kvm_state =3D NULL; > } [Severity: Low] Is kvm_close() synchronized with non-BQL callers of the ioctl wrappers? kvm_close() is called from vfio_cpr_kvm_close_notifier() on MIG_EVENT_PRECOPY_DONE, through vfio_kvm_device_close(). It does not call accel_ioctl_inhibit_begin(). The fds are closed with plain stores and no barrier: close(kvm_state->vmfd); kvm_state->vmfd =3D -1; close(kvm_state->fd); kvm_state->fd =3D -1; The later patch "kvm: fix coalesced MMIO flush racing with kvm_close()" only clears coalesced_mmio_ring and calls drain_call_rcu(). It does not add any synchronization to the fd close or to the new checks. > @@ -3371,6 +3370,11 @@ int kvm_ioctl(KVMState *s, unsigned long type, ...) > arg =3D va_arg(ap, void *); > va_end(ap); > =20 > + /* kvm_close() has been called: there is no KVM to talk to any more = */ > + if (s->fd =3D=3D -1) { > + return 0; > + } > + [Severity: Low] Can returning 0 for every system-level ioctl cause callers to act on a success that never happened? After kvm_close(), kvm_ioctl() fills in no output. For example, kvm_check_extension() sees 0 for KVM_CHECK_EXTENSION and so reports every capability as unsupported. > trace_kvm_ioctl(type, arg); > ret =3D ioctl(s->fd, type, arg); [ ... ] > @@ -3389,6 +3393,11 @@ int kvm_vm_ioctl(KVMState *s, unsigned long type, = ...) > arg =3D va_arg(ap, void *); > va_end(ap); > =20 > + /* kvm_close() has been called: there is no VM to talk to any more */ > + if (s->vmfd =3D=3D -1) { > + return 0; > + } > + [Severity: Medium] Can this fake 0 be mistaken for a valid file descriptor? Some kvm_vm_ioctl() requests return a new fd on success, and 0 is indistinguishable from fd 0 (normally stdin). Two paths are affected after kvm_close(). query_stats_cb() and query_stats_schemas_cb() only test for -1: stats_fd =3D kvm_vm_ioctl(s, KVM_GET_STATS_FD, NULL); if (stats_fd =3D=3D -1) { ... } query_stats(result, target, names, stats_fd, NULL, errp); close(stats_fd); Both callbacks are still registered after kvm_close(), so a QMP query-stats or query-stats-schemas would pass fd 0 to query_stats() and then call close(0). vfio_kvm_device_add_fd() in hw/vfio/helpers.c has the same problem: if (kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd)) { ... } vfio_kvm_device_fd =3D cd.fd; cd is initialized with only .type, so cd.fd stays 0. If a VFIO device is attached after kvm_close(), vfio_kvm_device_fd becomes 0, the next ioctl(0, KVM_SET_DEVICE_ATTR) fails with ENOTTY, and vfio_kvm_device_close() would later call close(0). kvm_create_guest_memfd() and kvm_create_vcpu() check only fd < 0, so they would also accept 0. I did not establish that either of them can run after kvm_close() on the source. The commit message justifies returning 0 only for interrupt and ioeventfd callers. Were the ioctls that return an fd audited? [Severity: Low] Can kvm_set_irq() return an uninitialized value after kvm_close()? kvm_set_irq() declares struct kvm_irq_level event; without an initializer and writes only level and irq: event.level =3D level; event.irq =3D irq; ret =3D kvm_vm_ioctl(s, s->irq_set_ioctl, &event); if (ret < 0) { perror("kvm_set_irq"); abort(); } return (s->irq_set_ioctl =3D=3D KVM_IRQ_LINE) ? 1 : event.status; With the new guard, kvm_vm_ioctl() returns 0 without running the ioctl, so the abort() check is skipped. On x86, irq_set_ioctl is KVM_IRQ_LINE_STATUS when KVM_CAP_IRQ_INJECT_STATUS is present, so event.status is returned uninitialized. kvm_ioapic_set_irq() reaches this path after kvm_close(), because kvm_state is no longer NULL: delivered =3D kvm_set_irq(kvm_state, s->kvm_gsi_base + irq, level); kvm_report_irq_delivered(delivered); The legacy PIC path, kvm_pic_set_irq(), does the same. Should event be zero-initialized, or should kvm_set_irq() return early when the VM is closed? The same shape applies to other getters such as KVM_GET_CLOCK, KVM_GET_IRQCHIP and KVM_GET_DIRTY_LOG, which would report success without filling the caller's buffer. I could not establish that any of them runs after kvm_close(). [Severity: Low] Is there a window between the new check and the ioctl() call? s->vmfd is read once for the check and again for ioctl(), and the check sits outside the accel_ioctl_begin()/accel_ioctl_end() region: if (s->vmfd =3D=3D -1) { return 0; } trace_kvm_vm_ioctl(type, arg); accel_ioctl_begin(); ret =3D ioctl(s->vmfd, type, arg); If a non-BQL thread passes the check just as kvm_close() closes the fds, the ioctl() can fail with EBADF. Callers such as kvm_set_irq() and kvm_irqchip_commit_routes() treat that as fatal. If the fd number has been reused, the ioctl lands on an unrelated fd. vCPU threads are stopped by cpu_remove_sync(), and the dirty-ring reaper takes the BQL. I could not show that every other non-BQL caller is excluded. This is speculative, and the window is narrow. > trace_kvm_vm_ioctl(type, arg); > accel_ioctl_begin(); > ret =3D ioctl(s->vmfd, type, arg); [ ... ] > @@ -3409,6 +3418,11 @@ int kvm_vcpu_ioctl(CPUState *cpu, unsigned long ty= pe, ...) > arg =3D va_arg(ap, void *); > va_end(ap); > =20 > + /* kvm_close() has been called: the vCPU fds are gone */ > + if (cpu->kvm_fd =3D=3D -1) { > + return 0; > + } > + [Severity: Low] Is cpu->kvm_fd =3D=3D -1 a reliable marker for the closed state? The guard returns success for any vCPU whose kvm_fd is -1, whether it was closed or never created. kvm_fd is set to -1 only in kvm_close(), so the guard is not tied to a dedicated closed state. Vector getters on this path would also report success without filling the caller's buffer. I did not establish that this path runs after kvm_close(). --=20 Sashiko AI review =C2=B7 https://sashiko.vzint.dev/#/patchset/20261020-vfio= _v1-v4-0-83a5668230e5@virtuozzo.com?part=3D20