From: Ying Gao ying01.gao@samsung.com
[ Upstream commit 528d92bfc0937a6a1ec837dbbcb3612a8545cd37 ]
When executing suspend to ram, if lacking the operations to reset device and free unused buffers before deleting a vq, resource leaks and inconsistent device status will appear.
According to chapter "3.3.1 Driver Requirements: Device Cleanup:" of virtio-specification: Driver MUST ensure a virtqueue isn’t live (by device reset) before removing exposed buffers.
Therefore, modify the virtinput_freeze function to reset the device and delete the unused buffers before deleting the virtqueue, just like virtinput_remove does.
Co-developed-by: Ying Xu ying123.xu@samsung.com Signed-off-by: Ying Xu ying123.xu@samsung.com Co-developed-by: Junnan Wu junnan01.wu@samsung.com Signed-off-by: Junnan Wu junnan01.wu@samsung.com Signed-off-by: Ying Gao ying01.gao@samsung.com Message-Id: 20250812095118.3622717-1-ying01.gao@samsung.com Signed-off-by: Michael S. Tsirkin mst@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
**Backport Status: YES**
## Extensive Analysis
This commit should be backported to stable kernel trees. Here's my detailed analysis based on the code changes and commit context:
### 1. **Bug Fix Nature** The commit fixes a clear resource leak bug in the virtio_input driver's suspend-to-RAM path. Looking at the code changes in `/home/sasha/linux/drivers/virtio/virtio_input.c:359-373`, the `virtinput_freeze()` function was missing critical cleanup steps that are present in `virtinput_remove()` (lines 340-356).
### 2. **Resource Leak Details** The specific issue involves: - **Memory leak**: The status queue (`vi->sts`) can contain allocated buffers (line 94 shows `virtqueue_add_outbuf` adds dynamically allocated `stsbuf` buffers via `kzalloc`). Without calling `virtqueue_detach_unused_buf()`, these buffers remain allocated but inaccessible after `del_vqs()`, causing memory leaks. - **Device state inconsistency**: Not calling `virtio_reset_device()` before deleting virtqueues violates the virtio specification requirement quoted in the commit message.
### 3. **Minimal and Contained Fix** The fix adds only 4 lines of code: ```c + void *buf; + virtio_reset_device(vdev); + while ((buf = virtqueue_detach_unused_buf(vi->sts)) != NULL) + kfree(buf); ``` This is a minimal change that mirrors what `virtinput_remove()` already does (lines 351-353), making it a low-risk fix.
### 4. **Real User Impact** This bug affects users who: - Use virtio input devices (keyboards, mice, tablets in VMs) - Perform suspend-to-RAM operations - Would experience cumulative memory leaks on each suspend/resume cycle
### 5. **Follows Established Pattern** Looking at commit `df4198b1e0c4a` from 2015, a similar fix was applied to the remove path to add device reset and buffer cleanup. This current commit extends that same pattern to the freeze path, showing consistency with previous fixes.
### 6. **Compliance with Virtio Specification** The commit explicitly addresses virtio specification compliance (chapter 3.3.1), which states that drivers MUST ensure virtqueues aren't live before removing exposed buffers. This is a correctness issue beyond just the memory leak.
### 7. **Similar Fixes in Other Drivers** Examining other virtio drivers like `virtio_balloon.c` (lines checked earlier), they properly reset the device in their freeze/remove paths, confirming this is the correct pattern.
### 8. **No Architectural Changes** The fix doesn't introduce: - New features - API changes - Complex logic modifications - Dependencies on other subsystems
It simply ensures proper cleanup during suspend, making it ideal for stable backporting.
### 9. **Low Regression Risk** The added code only runs during suspend-to-RAM, a well-defined path, and mirrors existing, tested code from the remove function. The risk of introducing new bugs is minimal.
This commit meets all criteria for stable backporting: it fixes a real bug with user impact (memory leaks and spec violation), the fix is small and contained, and it follows established patterns without introducing architectural changes.
drivers/virtio/virtio_input.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/virtio/virtio_input.c b/drivers/virtio/virtio_input.c index a5d63269f20b9..d0728285b6ce9 100644 --- a/drivers/virtio/virtio_input.c +++ b/drivers/virtio/virtio_input.c @@ -360,11 +360,15 @@ static int virtinput_freeze(struct virtio_device *vdev) { struct virtio_input *vi = vdev->priv; unsigned long flags; + void *buf;
spin_lock_irqsave(&vi->lock, flags); vi->ready = false; spin_unlock_irqrestore(&vi->lock, flags);
+ virtio_reset_device(vdev); + while ((buf = virtqueue_detach_unused_buf(vi->sts)) != NULL) + kfree(buf); vdev->config->del_vqs(vdev); return 0; }