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