virtualization.lists.linux-foundation.org archive mirror
 help / color / mirror / Atom feed
* [PATCH AUTOSEL 6.16-6.1] virtio_input: Improve freeze handling
       [not found] <20250902120833.1342615-1-sashal@kernel.org>
@ 2025-09-02 12:08 ` Sasha Levin
  2025-09-02 12:08 ` [PATCH AUTOSEL 6.16] virtio_net: adjust the execution order of function `virtnet_close` during freeze Sasha Levin
  1 sibling, 0 replies; 2+ messages in thread
From: Sasha Levin @ 2025-09-02 12:08 UTC (permalink / raw)
  To: patches, stable
  Cc: Ying Gao, Ying Xu, Junnan Wu, Michael S. Tsirkin, Sasha Levin,
	kraxel, jasowang, virtualization

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;
 }
-- 
2.50.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH AUTOSEL 6.16] virtio_net: adjust the execution order of function `virtnet_close` during freeze
       [not found] <20250902120833.1342615-1-sashal@kernel.org>
  2025-09-02 12:08 ` [PATCH AUTOSEL 6.16-6.1] virtio_input: Improve freeze handling Sasha Levin
@ 2025-09-02 12:08 ` Sasha Levin
  1 sibling, 0 replies; 2+ messages in thread
From: Sasha Levin @ 2025-09-02 12:08 UTC (permalink / raw)
  To: patches, stable
  Cc: Junnan Wu, Ying Xu, Michael S. Tsirkin, Sasha Levin, jasowang,
	andrew+netdev, davem, edumazet, kuba, pabeni, virtualization,
	netdev

From: Junnan Wu <junnan01.wu@samsung.com>

[ Upstream commit 45d8ef6322b8a828d3b1e2cfb8893e2ff882cb23 ]

"Use after free" issue appears in suspend once race occurs when
napi poll scheduls after `netif_device_detach` and before napi disables.

For details, during suspend flow of virtio-net,
the tx queue state is set to "__QUEUE_STATE_DRV_XOFF" by CPU-A.

And at some coincidental times, if a TCP connection is still working,
CPU-B does `virtnet_poll` before napi disable.
In this flow, the state "__QUEUE_STATE_DRV_XOFF"
of tx queue will be cleared. This is not the normal process it expects.

After that, CPU-A continues to close driver then virtqueue is removed.

Sequence likes below:
--------------------------------------------------------------------------
              CPU-A                            CPU-B
              -----                            -----
         suspend is called                  A TCP based on
                                        virtio-net still work
 virtnet_freeze
 |- virtnet_freeze_down
 | |- netif_device_detach
 | | |- netif_tx_stop_all_queues
 | |  |- netif_tx_stop_queue
 | |   |- set_bit
 | |     (__QUEUE_STATE_DRV_XOFF,...)
 | |                                     softirq rasied
 | |                                    |- net_rx_action
 | |                                     |- napi_poll
 | |                                      |- virtnet_poll
 | |                                       |- virtnet_poll_cleantx
 | |                                        |- netif_tx_wake_queue
 | |                                         |- test_and_clear_bit
 | |                                          (__QUEUE_STATE_DRV_XOFF,...)
 | |- virtnet_close
 |  |- virtnet_disable_queue_pair
 |   |- virtnet_napi_tx_disable
 |- remove_vq_common
--------------------------------------------------------------------------

When TCP delayack timer is up, a cpu gets softirq and irq handler
`tcp_delack_timer_handler` will be called, which will finally call
`start_xmit` in virtio net driver.
Then the access to tx virtq will cause panic.

The root cause of this issue is that napi tx
is not disable before `netif_tx_stop_queue`,
once `virnet_poll` schedules in such coincidental time,
the tx queue state will be cleared.

To solve this issue, adjusts the order of
function `virtnet_close` in `virtnet_freeze_down`.

Co-developed-by: Ying Xu <ying123.xu@samsung.com>
Signed-off-by: Ying Xu <ying123.xu@samsung.com>
Signed-off-by: Junnan Wu <junnan01.wu@samsung.com>
Message-Id: <20250812090817.3463403-1-junnan01.wu@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**

This commit should be backported to stable kernel trees. Here's my
extensive analysis:

## Critical Bug Fix
This commit fixes a **use-after-free vulnerability** in the virtio_net
driver that can cause kernel panics during system suspend. The issue is
a race condition between the suspend process and active network traffic,
specifically:

1. **Race Condition Details** (from commit message):
   - CPU-A calls `netif_device_detach()` which sets
     `__QUEUE_STATE_DRV_XOFF` on TX queues
   - CPU-B running `virtnet_poll()` can clear this flag via
     `netif_tx_wake_queue()`
   - CPU-A then calls `virtnet_close()` which disables NAPI and removes
     virtqueues
   - Later, when TCP delayed ACK timer fires, accessing the removed TX
     virtqueue causes a panic

## Code Analysis

The fix is **minimal and contained** - it simply reorders two operations
in `virtnet_freeze_down()`:

**Before (buggy order):**
```c
netif_tx_lock_bh(vi->dev);
netif_device_detach(vi->dev);  // Sets __QUEUE_STATE_DRV_XOFF
netif_tx_unlock_bh(vi->dev);
if (netif_running(vi->dev)) {
    virtnet_close(vi->dev);     // Disables NAPI - TOO LATE!
}
```

**After (fixed order):**
```c
if (netif_running(vi->dev)) {
    virtnet_close(vi->dev);     // Disables NAPI FIRST
}
netif_tx_lock_bh(vi->dev);
netif_device_detach(vi->dev);  // Then detach device
netif_tx_unlock_bh(vi->dev);
```

## Backport Suitability Criteria

1. **Fixes a real bug**: YES - Use-after-free causing kernel panics
2. **Small and contained**: YES - Only 8 lines moved, no logic changes
3. **No side effects**: YES - Just reordering existing operations
4. **No architectural changes**: YES - Simple ordering fix
5. **Critical subsystem**: YES - Network driver suspend/resume path
6. **Clear bug fix**: YES - Not a feature addition
7. **Minimal regression risk**: YES - The new order is logically correct
   (disable NAPI before marking queues stopped)

## Historical Context

From git blame analysis:
- The problematic code structure has existed since 2017 (commit
  9fe7bfce8b3e11)
- Recent changes in 2025 (commit e7231f49d52682) modified the locking
  but didn't fix the race
- This indicates the bug has been latent for **years** and affects many
  kernel versions

## Impact Assessment

- **Severity**: HIGH - Causes kernel panics during suspend with active
  network traffic
- **Likelihood**: MODERATE - Requires specific timing but can happen
  with normal TCP traffic
- **Affected systems**: All systems using virtio_net driver (VMs,
  containers)

The commit already has "[ Upstream commit
45d8ef6322b8a828d3b1e2cfb8893e2ff882cb23 ]" indicating it's been
identified for stable backporting, which further confirms its
importance.

 drivers/net/virtio_net.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 82b4a2a2b8c42..c9b18b13cd940 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -5728,14 +5728,15 @@ static void virtnet_freeze_down(struct virtio_device *vdev)
 	disable_rx_mode_work(vi);
 	flush_work(&vi->rx_mode_work);
 
-	netif_tx_lock_bh(vi->dev);
-	netif_device_detach(vi->dev);
-	netif_tx_unlock_bh(vi->dev);
 	if (netif_running(vi->dev)) {
 		rtnl_lock();
 		virtnet_close(vi->dev);
 		rtnl_unlock();
 	}
+
+	netif_tx_lock_bh(vi->dev);
+	netif_device_detach(vi->dev);
+	netif_tx_unlock_bh(vi->dev);
 }
 
 static int init_vqs(struct virtnet_info *vi);
-- 
2.50.1


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2025-09-02 12:08 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20250902120833.1342615-1-sashal@kernel.org>
2025-09-02 12:08 ` [PATCH AUTOSEL 6.16-6.1] virtio_input: Improve freeze handling Sasha Levin
2025-09-02 12:08 ` [PATCH AUTOSEL 6.16] virtio_net: adjust the execution order of function `virtnet_close` during freeze Sasha Levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).