virt: acrn: Fix irqfd use-after-free during eventfd shutdown
In the Linux kernel, the following vulnerability has been resolved: virt: acrn: Fix irqfd use-after-free during eventfd shutdown 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() deactivate
- Products
- Kernel
- Affected versions
- Not specified
- Fixed versions
- 6.1.191, 6.12.114, 6.18.53, 6.6.160
- CVEs
- CVE-2026-97478
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 5 Nov 2026, 01:53 UTC · Revision 1
Source evidence
virt: acrn: Fix irqfd use-after-free during eventfd shutdown
core-osv · Original sourcePublished 24 Sept 2026, 16:04 UTC
In the Linux kernel, the following vulnerability has been resolved: virt: acrn: Fix irqfd use-after-free during eventfd shutdown 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() deactivate
osv:CVE-2026-97478
Kernel
Fixed versions: 6.1.191, 6.6.160, 6.12.114, 6.18.53
Complete source record
{
"id": "dfa0b1301f1879ce0593e4342dbffe0731849f4fd576b2f374ce4095cd97d726",
"url": "https://osv.dev/vulnerability/CVE-2026-97478",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "virt: acrn: Fix irqfd use-after-free during eventfd shutdown",
"summary": "In the Linux kernel, the following vulnerability has been resolved: virt: acrn: Fix irqfd use-after-free during eventfd shutdown 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() deactivate",
"evidence": "osv:CVE-2026-97478",
"products": [
{
"name": {
"value": "Kernel",
"evidence": "/affected/1/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "6.1.191",
"evidence": "/affected/1/ranges"
},
{
"value": "6.6.160",
"evidence": "/affected/1/ranges"
},
{
"value": "6.12.114",
"evidence": "/affected/1/ranges"
},
{
"value": "6.18.53",
"evidence": "/affected/1/ranges"
}
],
"affected_versions": []
}
],
"severity": "high",
"structured": {
"id": "CVE-2026-97478",
"aliases": [
"CVE-2026-97478"
],
"metrics": [
{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H"
}
],
"affected": [
{
"ranges": [
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"type": "GIT",
"events": [
{
"introduced": "aa3b483ff1d71c50b33db154048dff9a8f08ac71"
},
{
"fixed": "dccf23a72a6c5ec8d9eab2a7f98e186af6eaff48"
},
{
"fixed": "6e9e007ee1dfb54bc2d070550308077ec28dbaec"
},
{
"fixed": "0e1152f689847b9db2f05454775d34610c1424c2"
},
{
"fixed": "d8156aacfcabb81f52c20ef89094945434d08079"
},
{
"fixed": "666c7f9e07925aa0863348f960e09bb89f8f05a3"
}
]
}
],
"database_specific": {
"source": "https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-97478.json"
}
},
{
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "5.12.0"
},
{
"fixed": "6.1.191"
}
]
},
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "6.2.0"
},
{
"fixed": "6.6.160"
}
]
},
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "6.7.0"
},
{
"fixed": "6.12.114"
}
]
},
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "6.13.0"
},
{
"fixed": "6.18.53"
}
]
}
],
"package": {
"name": "Kernel",
"ecosystem": "Linux"
},
"database_specific": {
"source": "https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-97478.json"
}
}
],
"modified": "2026-11-01T02:30:50.625706845Z",
"provider": "osv",
"references": [
"https://git.kernel.org/stable/c/0e1152f689847b9db2f05454775d34610c1424c2",
"https://git.kernel.org/stable/c/666c7f9e07925aa0863348f960e09bb89f8f05a3",
"https://git.kernel.org/stable/c/6e9e007ee1dfb54bc2d070550308077ec28dbaec",
"https://git.kernel.org/stable/c/d8156aacfcabb81f52c20ef89094945434d08079",
"https://git.kernel.org/stable/c/dccf23a72a6c5ec8d9eab2a7f98e186af6eaff48",
"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/97xxx/CVE-2026-97478.json",
"https://nvd.nist.gov/vuln/detail/CVE-2026-97478",
"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"
],
"provider_metadata": {
"cna_assigner": "Linux",
"osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/97xxx/CVE-2026-97478.json"
}
},
"related_cves": [
{
"value": "CVE-2026-97478",
"evidence": "/id"
}
],
"security_relevant": true,
"severity_evidence": "/severity/0/score"
},
"source_id": "core-osv",
"document_id": 509245,
"published_at": "2026-09-24T16:04:20.263+00:00"
}