[PATCH v3 17/17] firmware: arm_scmi: Clear virtio channel lists on free

Sudeep Holla sudeep.holla at kernel.org
Fri Jul 3 13:22:53 PDT 2026


SCMI virtio messages are allocated with devres against the SCMI
platform device, while the virtio channel structures are owned by the
virtio device and can survive SCMI driver unbind and rebind.

virtio_chan_free() only synchronizes channel shutdown. It leaves message
pointers on the channel free list, and possibly on the deferred pending
list or virtqueue, until SCMI devres later frees the messages. A
subsequent SCMI bind can then reuse stale list entries and dereference
freed memory.

After synchronized shutdown, detach any unused virtqueue buffers and
reinitialize both local message lists so no SCMI-devres message pointers
remain in virtio channel state.

Fixes: 5ffc1c4cb896 ("firmware: arm_scmi: Fix devres allocation device in virtio transport")
Reported-by: Sashiko <sashiko-bot at kernel.org>
Signed-off-by: Sudeep Holla <sudeep.holla at kernel.org>
---
 drivers/firmware/arm_scmi/transports/virtio.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/firmware/arm_scmi/transports/virtio.c b/drivers/firmware/arm_scmi/transports/virtio.c
index 3282d8271839..c4738b866d62 100644
--- a/drivers/firmware/arm_scmi/transports/virtio.c
+++ b/drivers/firmware/arm_scmi/transports/virtio.c
@@ -178,6 +178,22 @@ static void scmi_vio_channel_cleanup_sync(struct scmi_vio_channel *vioch)
 	wait_for_completion(vioch->shutdown_done);
 }
 
+static void scmi_vio_channel_cleanup(struct scmi_vio_channel *vioch)
+{
+	unsigned long flags;
+
+	while (virtqueue_detach_unused_buf(vioch->vqueue))
+		;
+
+	spin_lock_irqsave(&vioch->free_lock, flags);
+	INIT_LIST_HEAD(&vioch->free_list);
+	spin_unlock_irqrestore(&vioch->free_lock, flags);
+
+	spin_lock_irqsave(&vioch->pending_lock, flags);
+	INIT_LIST_HEAD(&vioch->pending_cmds_list);
+	spin_unlock_irqrestore(&vioch->pending_lock, flags);
+}
+
 /* Assumes to be called with vio channel acquired already */
 static struct scmi_vio_msg *
 scmi_virtio_get_free_msg(struct scmi_vio_channel *vioch)
@@ -484,6 +500,7 @@ static int virtio_chan_free(int id, void *p, void *data)
 	 */
 	virtio_break_device(vioch->vqueue->vdev);
 	scmi_vio_channel_cleanup_sync(vioch);
+	scmi_vio_channel_cleanup(vioch);
 
 	return 0;
 }

-- 
2.43.0




More information about the linux-arm-kernel mailing list