* [PATCH net v2 0/2] vsock/virtio: fix msg_iter desync on transmission failure
@ 2026-06-13 0:09 Octavian Purdila
2026-06-13 0:09 ` [PATCH net v2 1/2] iov_iter: export iov_iter_restore Octavian Purdila
2026-06-13 0:09 ` [PATCH net v2 2/2] vsock/virtio: restore msg_iter on transmission failure Octavian Purdila
0 siblings, 2 replies; 5+ messages in thread
From: Octavian Purdila @ 2026-06-13 0:09 UTC (permalink / raw)
To: netdev
Cc: Alexander Viro, Andrew Morton, Arseniy Krasnov, David S. Miller,
Eric Dumazet, Eugenio Pérez, Jakub Kicinski, Jason Wang, kvm,
linux-block, linux-fsdevel, linux-kernel, Michael S. Tsirkin,
Paolo Abeni, Simon Horman, Stefan Hajnoczi, Stefano Garzarella,
virtualization, Xuan Zhuo, Octavian Purdila
This series fixes a msg_iter desync issue in the virtio vsock transport
that can lead to warnings and eventual -ENOMEM under specific failure
scenarios (e.g. partial GUP failure during MSG_ZEROCOPY transmission).
To fix this, we need to restore the msg_iter state on transmission failure.
However, since virtio vsock transport can be built as a module, we first
need to export iov_iter_restore.
Patch 1 exports iov_iter_restore.
Patch 2 implements the msg_iter restoration in virtio vsock.
Changes in v2:
- Use iov_iter_savestate()/iov_iter_restore() (Stefano)
- Use a single restore point (Stefano)
- Reverse xmas tree (Stefano)
- Added comments in the code (Stefano)
v1: https://lore.kernel.org/all/20260609004809.1285028-1-tavip@google.com/
Octavian Purdila (2):
iov_iter: export iov_iter_restore
vsock/virtio: restore msg_iter on transmission failure
lib/iov_iter.c | 1 +
net/vmw_vsock/virtio_transport_common.c | 13 +++++++++++++
2 files changed, 14 insertions(+)
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net v2 1/2] iov_iter: export iov_iter_restore
2026-06-13 0:09 [PATCH net v2 0/2] vsock/virtio: fix msg_iter desync on transmission failure Octavian Purdila
@ 2026-06-13 0:09 ` Octavian Purdila
2026-06-14 0:10 ` sashiko-bot
2026-06-13 0:09 ` [PATCH net v2 2/2] vsock/virtio: restore msg_iter on transmission failure Octavian Purdila
1 sibling, 1 reply; 5+ messages in thread
From: Octavian Purdila @ 2026-06-13 0:09 UTC (permalink / raw)
To: netdev
Cc: Alexander Viro, Andrew Morton, Arseniy Krasnov, David S. Miller,
Eric Dumazet, Eugenio Pérez, Jakub Kicinski, Jason Wang, kvm,
linux-block, linux-fsdevel, linux-kernel, Michael S. Tsirkin,
Paolo Abeni, Simon Horman, Stefan Hajnoczi, Stefano Garzarella,
virtualization, Xuan Zhuo, Octavian Purdila
Export iov_iter_restore so that it can be used by modules.
This is needed by the virtio vsock transport (which can be built as a
module) to restore the msg_iter state when transmission fails.
Signed-off-by: Octavian Purdila <tavip@google.com>
---
lib/iov_iter.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 243662af1af73..067e745f9ef53 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -1491,6 +1491,7 @@ void iov_iter_restore(struct iov_iter *i, struct iov_iter_state *state)
i->__iov -= state->nr_segs - i->nr_segs;
i->nr_segs = state->nr_segs;
}
+EXPORT_SYMBOL(iov_iter_restore);
/*
* Extract a list of contiguous pages from an ITER_FOLIOQ iterator. This does
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH net v2 2/2] vsock/virtio: restore msg_iter on transmission failure
2026-06-13 0:09 [PATCH net v2 0/2] vsock/virtio: fix msg_iter desync on transmission failure Octavian Purdila
2026-06-13 0:09 ` [PATCH net v2 1/2] iov_iter: export iov_iter_restore Octavian Purdila
@ 2026-06-13 0:09 ` Octavian Purdila
2026-06-14 0:10 ` sashiko-bot
1 sibling, 1 reply; 5+ messages in thread
From: Octavian Purdila @ 2026-06-13 0:09 UTC (permalink / raw)
To: netdev
Cc: Alexander Viro, Andrew Morton, Arseniy Krasnov, David S. Miller,
Eric Dumazet, Eugenio Pérez, Jakub Kicinski, Jason Wang, kvm,
linux-block, linux-fsdevel, linux-kernel, Michael S. Tsirkin,
Paolo Abeni, Simon Horman, Stefan Hajnoczi, Stefano Garzarella,
virtualization, Xuan Zhuo, Octavian Purdila,
syzbot+28e5f3d207b14bae122a
When transmission fails in virtio_transport_send_pkt_info, the msg_iter
might have been partially advanced. If we don't restore it, the next
attempt to send data will use an incorrect iterator state, leading to
desync and warnings like "send_pkt() returns 0, but X expected".
Specifically, this can happen in the following scenario, triggered by
the syzkaller repro:
1. A write-only VMA (PROT_WRITE only) is partially populated by a
prior TUN write that failed with -EIO but still faulted in some
pages).
2. A vsock sendmmsg call with MSG_ZEROCOPY requests transmission of a
buffer from this VMA.
3. The first packet (64KB) is sent successfully because the pages are
populated.
4. The second packet allocation fails because GUP fast pins the first page
but GUP slow fails on the next unpopulated page due to PROT_WRITE-only
permissions.
5. The iterator is advanced by the partially successful GUP (68KB total
advanced: 64KB from first packet + 4KB from second), but the send loop
breaks and only reports 64KB sent. This creates a 4KB desync.
6. The next retry starts with a non-zero iov_offset, disabling zerocopy
and falling back to copy mode.
7. In copy mode, the transmission succeeds for the next packets but
exhausts the iterator early because of the desync.
8. The final retry sees an empty iterator but zerocopy is re-enabled
(offset resets). It attempts to send the remaining bytes with zerocopy
but pins 0 pages, creating an empty packet.
9. The transport sends the empty packet, triggering the warning because
the returned bytes (header only) do not match the expected payload size.
10. The loop continues to spin, allocating ubuf_info each time, eventually
exhausting sysctl_optmem_max and returning -ENOMEM to userspace.
Restore msg_iter to its original state before the packet allocation
and transmission attempt if they fail.
Fixes: e0718bd82e27 ("vsock: enable setting SO_ZEROCOPY")
Reported-by: syzbot+28e5f3d207b14bae122a@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=28e5f3d207b14bae122a
Assisted-by: gemini:gemini-3.1-pro
Signed-off-by: Octavian Purdila <tavip@google.com>
---
net/vmw_vsock/virtio_transport_common.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
index b10666937c490..2baa5a6ebd750 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -295,6 +295,7 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
u32 max_skb_len = VIRTIO_VSOCK_MAX_PKT_BUF_SIZE;
u32 src_cid, src_port, dst_cid, dst_port;
const struct virtio_transport *t_ops;
+ struct iov_iter_state msg_iter_state;
struct virtio_vsock_sock *vvs;
struct ubuf_info *uarg = NULL;
u32 pkt_len = info->pkt_len;
@@ -368,8 +369,17 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
struct sk_buff *skb;
size_t skb_len;
+ /* Save iterator state in case allocation or transmission fails
+ * so we can restore it and retry.
+ */
+ if (info->msg)
+ iov_iter_save_state(&info->msg->msg_iter, &msg_iter_state);
+
skb_len = min(max_skb_len, rest_len);
+ /* Note: virtio_transport_alloc_skb() can advance info->msg->msg_iter
+ * even if it fails (e.g. partial GUP success).
+ */
skb = virtio_transport_alloc_skb(info, skb_len, can_zcopy,
uarg,
src_cid, src_port,
@@ -399,6 +409,9 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
break;
} while (rest_len);
+ if (info->msg && ret < 0)
+ iov_iter_restore(&info->msg->msg_iter, &msg_iter_state);
+
virtio_transport_put_credit(vvs, rest_len);
/* msg_zerocopy_realloc() initializes the ubuf_info refcnt to 1.
--
2.54.0.1136.gdb2ca164c4-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH net v2 1/2] iov_iter: export iov_iter_restore
2026-06-13 0:09 ` [PATCH net v2 1/2] iov_iter: export iov_iter_restore Octavian Purdila
@ 2026-06-14 0:10 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-06-14 0:10 UTC (permalink / raw)
To: Octavian Purdila; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [High] Exporting iov_iter_restore() and using it for generic transports is unsafe, as it fundamentally lacks support for modern iterators (ITER_FOLIOQ, ITER_XARRAY) and corrupts state.
Pre-existing issues:
- [High] iov_iter_restore() contains a parenthesis error in its WARN_ON_ONCE condition, causing it to spuriously emit a kernel warning when called with an ITER_KVEC iterator.
--
commit 169d794e6c649159c82a4c128f4edf768368df54
Author: Octavian Purdila <tavip@google.com>
iov_iter: export iov_iter_restore
Export iov_iter_restore so that it can be used by modules.
This is needed by the virtio vsock transport (which can be built as a
module) to restore the msg_iter state when transmission fails.
> diff --git a/lib/iov_iter.c b/lib/iov_iter.c
> --- a/lib/iov_iter.c
> +++ b/lib/iov_iter.c
> @@ -1469,28 +1469,29 @@ void iov_iter_restore(struct iov_iter *i, struct iov_iter_state *state)
> {
> if (WARN_ON_ONCE(!iov_iter_is_bvec(i) && !iter_is_iovec(i) &&
> !iter_is_ubuf(i)) && !iov_iter_is_kvec(i))
> return;
[Severity: High]
This is a pre-existing issue, but does the WARN_ON_ONCE condition have a
misplaced closing parenthesis?
If an ITER_KVEC is passed, the first three checks evaluate to true, so
WARN_ON_ONCE(true) is executed, triggering a spurious stack trace dump. The
function proceeds correctly because the overall condition evaluates to false,
but exporting this makes the bug accessible to generic users.
[ ... ]
> if (iov_iter_is_bvec(i))
> i->bvec -= state->nr_segs - i->nr_segs;
> else
> i->__iov -= state->nr_segs - i->nr_segs;
> i->nr_segs = state->nr_segs;
> }
> +EXPORT_SYMBOL(iov_iter_restore);
[Severity: High]
Is it safe to export iov_iter_restore for generic socket transports?
The struct iov_iter_state lacks the fields necessary to track list traversal
or state for complex iterators, such as the folioq pointer in ITER_FOLIOQ.
Because of this, iov_iter_restore() silently returns without doing anything
for these types.
If a generic transport receives an ITER_FOLIOQ or ITER_XARRAY iterator, the
state will not be reverted on failure, which could lead to data corruption or
desynchronization upon retry. Should transports save and restore the full
struct iov_iter by value instead, or use iov_iter_revert()?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260613000953.467473-1-tavip@google.com?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net v2 2/2] vsock/virtio: restore msg_iter on transmission failure
2026-06-13 0:09 ` [PATCH net v2 2/2] vsock/virtio: restore msg_iter on transmission failure Octavian Purdila
@ 2026-06-14 0:10 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-06-14 0:10 UTC (permalink / raw)
To: Octavian Purdila; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Use of `iov_iter_restore` causes spurious `WARN_ON_ONCE` for `ITER_KVEC` iterators and lacks support for `ITER_FOLIOQ`, risking state corruption.
--
commit adc9013e2e0f53e4c04e792c4d6b248a3f5afb54
Author: Octavian Purdila <tavip@google.com>
vsock/virtio: restore msg_iter on transmission failure
This commit addresses an iterator desync issue when packet allocation or
transmission fails by saving the msg_iter state before attempting to allocate
and send, and restoring it if an error occurs.
> --- a/net/vmw_vsock/virtio_transport_common.c
> +++ b/net/vmw_vsock/virtio_transport_common.c
> @@ -368,8 +369,17 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
> struct sk_buff *skb;
> size_t skb_len;
>
> + /* Save iterator state in case allocation or transmission fails
> + * so we can restore it and retry.
> + */
> + if (info->msg)
> + iov_iter_save_state(&info->msg->msg_iter, &msg_iter_state);
> +
> skb_len = min(max_skb_len, rest_len);
>
> + /* Note: virtio_transport_alloc_skb() can advance info->msg->msg_iter
> + * even if it fails (e.g. partial GUP success).
> + */
> skb = virtio_transport_alloc_skb(info, skb_len, can_zcopy,
> uarg,
> src_cid, src_port,
[ ... ]
> @@ -399,6 +409,9 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
> break;
> } while (rest_len);
>
> + if (info->msg && ret < 0)
> + iov_iter_restore(&info->msg->msg_iter, &msg_iter_state);
> +
[Severity: Medium]
Does this iov_iter_restore() call risk triggering a spurious warning for
ITER_KVEC iterators or silently failing for ITER_FOLIOQ?
In-kernel socket consumers, such as the Network Block Device, actively
construct ITER_KVEC iterators for request headers and send them via
sock_sendmsg(). Users can configure NBD over a vsock socket.
If memory pressure causes virtio_transport_alloc_skb() to fail during an
NBD transmission, the error path invokes iov_iter_restore() which evaluates
the following condition:
lib/iov_iter.c:iov_iter_restore() {
if (WARN_ON_ONCE(!iov_iter_is_bvec(i) && !iter_is_iovec(i) &&
!iter_is_ubuf(i)) && !iov_iter_is_kvec(i))
return;
...
}
For ITER_KVEC iterators, the first part of the expression evaluates to true,
unconditionally triggering a kernel warning before restoring the iterator. On
systems with panic_on_warn enabled, this could lead to a kernel panic.
Additionally, iov_iter_restore() explicitly ignores ITER_FOLIOQ iterators,
meaning it would silently fail to restore the state if the VFS passes such
an iterator, potentially leading to infinite loops and desynchronization.
Could tracking the number of bytes advanced and using iov_iter_revert()
provide a safer way to handle this rollback?
> virtio_transport_put_credit(vvs, rest_len);
>
> /* msg_zerocopy_realloc() initializes the ubuf_info refcnt to 1.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260613000953.467473-1-tavip@google.com?part=2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-06-14 0:10 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-13 0:09 [PATCH net v2 0/2] vsock/virtio: fix msg_iter desync on transmission failure Octavian Purdila
2026-06-13 0:09 ` [PATCH net v2 1/2] iov_iter: export iov_iter_restore Octavian Purdila
2026-06-14 0:10 ` sashiko-bot
2026-06-13 0:09 ` [PATCH net v2 2/2] vsock/virtio: restore msg_iter on transmission failure Octavian Purdila
2026-06-14 0:10 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox