[PATCH OLK-6.6 0/3] CVE-2026-90129
CVE-2026-90129 Denis V. Lunev (3): virtio: add virtio_device_shutdown() helper virtio_balloon: factor out virtballoon_quiesce() virtio_balloon: quiesce balloon work before device shutdown drivers/virtio/virtio.c | 41 ++++++++++++++++++++++----------- drivers/virtio/virtio_balloon.c | 34 +++++++++++++++++++++------ include/linux/virtio.h | 1 + 3 files changed, 55 insertions(+), 21 deletions(-) -- 2.34.1
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/29471 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/XMB... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/29471 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/XMB...
From: "Denis V. Lunev" <den@openvz.org> mainline inclusion from mainline-v7.3-rc1 commit 0d8aebe089b4ba887e792884cf041ce9f1040ff4 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/19410 CVE: CVE-2026-90129 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- The generic virtio bus .shutdown handler, virtio_dev_shutdown(), breaks and resets a device once it has established that the driver has no .shutdown of its own. A driver that does implement .shutdown, to quiesce its own activity first, still needs the same break and reset afterwards and would otherwise have to open code it. Factor the break + synchronize_cbs + reset sequence out of virtio_dev_shutdown() into an exported virtio_device_shutdown() helper so such drivers can reuse it instead of duplicating the core logic. No functional change. Signed-off-by: Denis V. Lunev <den@openvz.org> Reviewed-by: David Hildenbrand (Arm) <david@kernel.org> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20260624140846.2616797-2-den@openvz.org> Conflicts: drivers/virtio/virtio.c include/linux/virtio.h [Context conflicts. The virtio_irq_get_affinity() hunk added by an unrelated commit is not present in this tree, so only the helper is added.] Signed-off-by: Jiacheng Yu <yujiacheng3@huawei.com> --- drivers/virtio/virtio.c | 41 +++++++++++++++++++++++++++-------------- include/linux/virtio.h | 1 + 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 9518583d1512..2ac2960696cf 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -340,6 +340,32 @@ static void virtio_dev_remove(struct device *_d) of_node_put(dev->dev.of_node); } +/** + * virtio_device_shutdown - break and reset a device on shutdown + * @dev: the device + * + * Drivers with their own .shutdown method should quiesce their activity and + * then call this to stop the device the way the generic shutdown path does. + */ +void virtio_device_shutdown(struct virtio_device *dev) +{ + /* + * Some devices get wedged if you kick them after they are + * reset. Mark all vqs as broken to make sure we don't. + */ + virtio_break_device(dev); + /* + * Guarantee that any callback will see vq->broken as true. + */ + virtio_synchronize_cbs(dev); + /* + * As IOMMUs are reset on shutdown, this will block device access to memory. + * Some devices get wedged if this happens, so reset to make sure it does not. + */ + dev->config->reset(dev); +} +EXPORT_SYMBOL_GPL(virtio_device_shutdown); + static void virtio_dev_shutdown(struct device *_d) { struct virtio_device *dev = dev_to_virtio(_d); @@ -358,20 +384,7 @@ static void virtio_dev_shutdown(struct device *_d) return; } - /* - * Some devices get wedged if you kick them after they are - * reset. Mark all vqs as broken to make sure we don't. - */ - virtio_break_device(dev); - /* - * Guarantee that any callback will see vq->broken as true. - */ - virtio_synchronize_cbs(dev); - /* - * As IOMMUs are reset on shutdown, this will block device access to memory. - * Some devices get wedged if this happens, so reset to make sure it does not. - */ - dev->config->reset(dev); + virtio_device_shutdown(dev); } static struct bus_type virtio_bus = { diff --git a/include/linux/virtio.h b/include/linux/virtio.h index d8caaefba1d8..feeaaf9dd1b9 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -154,6 +154,7 @@ int virtio_device_freeze(struct virtio_device *dev); int virtio_device_restore(struct virtio_device *dev); #endif void virtio_reset_device(struct virtio_device *dev); +void virtio_device_shutdown(struct virtio_device *dev); size_t virtio_max_dma_size(const struct virtio_device *vdev); -- 2.34.1
From: "Denis V. Lunev" <den@openvz.org> mainline inclusion from mainline-v7.3-rc1 commit 29536a923a9412812eb3e378258019b54538a220 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/19410 CVE: CVE-2026-90129 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- virtballoon_remove() stops all of the balloon's asynchronous work (the free page reporting worker, the inflate/deflate and stats workers, the OOM notifier and the free page shrinker) before tearing the device down. A following change needs the same teardown from a .shutdown handler, so move it into a virtballoon_quiesce() helper. No functional change. Signed-off-by: Denis V. Lunev <den@openvz.org> Reviewed-by: David Hildenbrand (Arm) <david@kernel.org> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20260624140846.2616797-3-den@openvz.org> Conflicts: drivers/virtio/virtio_balloon.c [This tree carries a vendor-specific memop_work worker, whose cancel_work_sync() is kept inside virtballoon_quiesce().] Signed-off-by: Jiacheng Yu <yujiacheng3@huawei.com> --- drivers/virtio/virtio_balloon.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 8f45ee1c959b..b14fafcf8c6e 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -1214,16 +1214,21 @@ static void remove_common(struct virtio_balloon *vb) vb->vdev->config->del_vqs(vb->vdev); } -static void virtballoon_remove(struct virtio_device *vdev) +/* + * Stop all asynchronous balloon work. The device must still be alive so that + * in-flight requests can drain via the host before it is reset or freed. + */ +static void virtballoon_quiesce(struct virtio_balloon *vb) { - struct virtio_balloon *vb = vdev->priv; + struct virtio_device *vdev = vb->vdev; - if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) + if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_REPORTING)) page_reporting_unregister(&vb->pr_dev_info); - if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) + if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM)) unregister_oom_notifier(&vb->oom_nb); - if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) + if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) virtio_balloon_unregister_shrinker(vb); + spin_lock_irq(&vb->stop_update_lock); vb->stop_update = true; spin_unlock_irq(&vb->stop_update_lock); @@ -1233,10 +1238,18 @@ static void virtballoon_remove(struct virtio_device *vdev) cancel_work_sync(&vb->memop_work); #endif - if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) { + if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) cancel_work_sync(&vb->report_free_page_work); +} + +static void virtballoon_remove(struct virtio_device *vdev) +{ + struct virtio_balloon *vb = vdev->priv; + + virtballoon_quiesce(vb); + + if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) destroy_workqueue(vb->balloon_wq); - } remove_common(vb); kfree(vb); -- 2.34.1
From: "Denis V. Lunev" <den@openvz.org> mainline inclusion from mainline-v7.3-rc1 commit 7e17eef04600c399c7e0f5ce765da5cf9d40d8e1 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/19410 CVE: CVE-2026-90129 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- Commit 8bd2fa086a04 ("virtio: break and reset virtio devices on device_shutdown()") added a generic virtio bus .shutdown handler that breaks and resets every virtio device during device_shutdown(), i.e. on reboot and kexec. virtio_balloon provides no .shutdown of its own, so that generic path runs while the balloon's asynchronous work is still armed. Once the device has been broken, virtqueue_add_inbuf() in virtballoon_free_page_report() returns -EIO and trips its WARN_ON_ONCE(). On a kernel booted with panic_on_warn that turns an ordinary reboot, for example a kexec based upgrade, into a fatal panic in the middle of device_shutdown(), so the machine never reaches the new kernel. Relaxing that single WARN_ON_ONCE() would only hide the symptom: the inflate/deflate and OOM paths do not warn, they call wait_event(vb->acked, ...) and would instead block forever on a broken queue that can no longer complete. The device has to be quiesced, not just kept quiet. Add a .shutdown handler that quiesces the balloon via the shared virtballoon_quiesce() helper while the device is still alive, and only then breaks and resets it via virtio_device_shutdown(). Unlike virtballoon_remove() the balloon workqueue is not destroyed, as shutdown does not free the device and cancel_work_sync() together with stop_update already prevent any further work from being queued. Fixes: 8bd2fa086a04 ("virtio: break and reset virtio devices on device_shutdown()") Signed-off-by: Denis V. Lunev <den@openvz.org> Reviewed-by: David Hildenbrand (Arm) <david@kernel.org> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20260624140846.2616797-4-den@openvz.org> Signed-off-by: Jiacheng Yu <yujiacheng3@huawei.com> --- drivers/virtio/virtio_balloon.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index b14fafcf8c6e..8181f058b78c 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -1255,6 +1255,12 @@ static void virtballoon_remove(struct virtio_device *vdev) kfree(vb); } +static void virtballoon_shutdown(struct virtio_device *vdev) +{ + virtballoon_quiesce(vdev->priv); + virtio_device_shutdown(vdev); +} + #ifdef CONFIG_PM_SLEEP static int virtballoon_freeze(struct virtio_device *vdev) { @@ -1345,6 +1351,7 @@ static struct virtio_driver virtio_balloon_driver = { .validate = virtballoon_validate, .probe = virtballoon_probe, .remove = virtballoon_remove, + .shutdown = virtballoon_shutdown, .config_changed = virtballoon_changed, #ifdef CONFIG_PM_SLEEP .freeze = virtballoon_freeze, -- 2.34.1
participants (2)
-
Jiacheng Yu -
patchwork bot