Netdev List
 help / color / mirror / Atom feed
* [PATCH net v2 0/2] packet: fix PACKET_TX_RING data corruption on skb_orphan
@ 2026-09-19  0:47 Willem de Bruijn
  2026-09-19  0:47 ` [PATCH net v2 1/2] virtio_net: copy zerocopy frags in start_xmit without NAPI Willem de Bruijn
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Willem de Bruijn @ 2026-09-19  0:47 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuba, edumazet, pabeni, horms, andrew+netdev,
	Willem de Bruijn

From: Willem de Bruijn <willemb@google.com>

When transmitting packets via PACKET_TX_RING, tpacket_snd links user
ring buffer pages as skb frags and releases the slot on skb->destructor
(tpacket_destruct_skb).

skb_orphan() invokes the destructor while the skb is still alive.
This marks the slot as TP_STATUS_AVAILABLE prematurely, allowing
userspace to overwrite the slot and causing data corruption.

This series fixes the issue by switching PACKET_TX_RING to standard
ubuf_info zerocopy completion, ensuring ring slots are released only
after all payload references are freed or copied.

Virtio-net needs a separate solution, because deferring the release
can cause deadlock in its !use_napi mode.

- Patch 1 addresses the virtio-net special case.
- Patch 2 converts tpacket_snd to standard ubuf_info completion

Patch 1 must be applied, and backported, before patch 2. Both carry
the same Fixes tag for that reason.

v1: https://lore.kernel.org/netdev/20260914214229.1674102-1-willemdebruijn.kernel@gmail.com/

Willem de Bruijn (2):
  virtio_net: copy zerocopy frags in start_xmit without NAPI
  packet: use ubuf_info completion for TX_RING packets

 drivers/net/virtio_net.c |   9 ++++
 include/linux/skbuff.h   |  19 +-------
 net/packet/af_packet.c   | 102 ++++++++++++++++++++++++---------------
 3 files changed, 74 insertions(+), 56 deletions(-)

-- 
2.55.0.1082.g2b9226bbc0-goog


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

* [PATCH net v2 1/2] virtio_net: copy zerocopy frags in start_xmit without NAPI
  2026-09-19  0:47 [PATCH net v2 0/2] packet: fix PACKET_TX_RING data corruption on skb_orphan Willem de Bruijn
@ 2026-09-19  0:47 ` Willem de Bruijn
  2026-09-22  3:49   ` netdev-bot+sashiko
  2026-09-19  0:47 ` [PATCH net v2 2/2] packet: use ubuf_info completion for TX_RING packets Willem de Bruijn
  2026-09-23  2:00 ` [PATCH net v2 0/2] packet: fix PACKET_TX_RING data corruption on skb_orphan patchwork-bot+netdevbpf
  2 siblings, 1 reply; 8+ messages in thread
From: Willem de Bruijn @ 2026-09-19  0:47 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuba, edumazet, pabeni, horms, andrew+netdev,
	Willem de Bruijn, stable, mst, jasowangio

From: Willem de Bruijn <willemb@google.com>

Virtio-net without NAPI frees completed skbs lazily on the next
start_xmit. Senders waiting for in-flight zerocopy buffers can
deadlock if they cannot transmit more packets, as then no
completed packets will be freed.

When !use_napi, virtio-net already calls skb_orphan to avoid waiting
up for transmitted skbs to be freed. For zerocopy packets that
require deep copying on orphan (i.e. those that do not set
SKBFL_DONT_ORPHAN, such as PACKET_TX_RING), call skb_orphan_frags
before orphaning to release the buffers.

This fixes the tpacket_snd slot reuse bug on skb_orphan for
virtio-net, and prevents PACKET_TX_RING from running out of slots.

This fix also touches vhost_net zerocopy packets, which also do not
set SKBFL_DONT_ORPHAN. This is fine: vhost_net packets only encounter
virtio-net in nested virtualization, and only if napi_tx is
explicitly disabled (it has been default-enabled since Linux 4.12).
In that rare case, copying the frags is desirable anyway to prevent
holding guest descriptors pinned across unbounded intervals.

This is a prerequisite for the next patch, which converts
PACKET_TX_RING to standard zerocopy completion. Without this patch
first, a bounded ring sender can stall indefinitely behind a
virtio-net virtqueue that cannot reclaim.

Fixes: 5cd8d46ea156 ("packet: copy user buffers before orphan or clone")
Cc: stable@vger.kernel.org
Cc: mst@redhat.com
Cc: jasowangio@gmail.com
Signed-off-by: Willem de Bruijn <willemb@google.com>

---

v1->v2
  - Do not suppress device kick on skb_orphan_frags error when !xmit_more

---
 drivers/net/virtio_net.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index e34c52d059d3..bf82ef9874ab 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3349,6 +3349,14 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 	else
 		virtqueue_disable_cb(sq->vq);
 
+	if (!use_napi &&
+	    unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) {
+		DEV_STATS_INC(dev, tx_dropped);
+		dev_kfree_skb_any(skb);
+		kick = !xmit_more || netif_xmit_stopped(txq);
+		goto kick_vq;
+	}
+
 	/* timestamp packet in software */
 	skb_tx_timestamp(skb);
 
@@ -3381,6 +3389,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	kick = use_napi ? __netdev_tx_sent_queue(txq, skb->len, xmit_more) :
 			  !xmit_more || netif_xmit_stopped(txq);
+kick_vq:
 	if (kick) {
 		if (virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq)) {
 			u64_stats_update_begin(&sq->stats.syncp);
-- 
2.55.0.1082.g2b9226bbc0-goog


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

* [PATCH net v2 2/2] packet: use ubuf_info completion for TX_RING packets
  2026-09-19  0:47 [PATCH net v2 0/2] packet: fix PACKET_TX_RING data corruption on skb_orphan Willem de Bruijn
  2026-09-19  0:47 ` [PATCH net v2 1/2] virtio_net: copy zerocopy frags in start_xmit without NAPI Willem de Bruijn
@ 2026-09-19  0:47 ` Willem de Bruijn
  2026-09-22  3:49   ` netdev-bot+sashiko
  2026-09-23  2:00 ` [PATCH net v2 0/2] packet: fix PACKET_TX_RING data corruption on skb_orphan patchwork-bot+netdevbpf
  2 siblings, 1 reply; 8+ messages in thread
From: Willem de Bruijn @ 2026-09-19  0:47 UTC (permalink / raw)
  To: netdev
  Cc: davem, kuba, edumazet, pabeni, horms, andrew+netdev,
	Willem de Bruijn, Katherine Leaver, Bjoern Doebel, stable

From: Willem de Bruijn <willemb@google.com>

tpacket_snd sends skbs with frags pointing into its ring slots. Slots
are released when skb->destructor is called.

A call to skb_orphan calls skb->destructor before the skb is freed.
This can cause the slot to be reused while still linked into the skb.

Switch to standard zerocopy completion (ubuf_info) so the slot is only
released once all references to the payload are freed or copied.
Restore skb->destructor to standard sock_wfree.

The ubuf_info completion callback can be called with a NULL skb, but
only from net_zcopy_put and related API, used by zerocopy implementations
that hold their own reference on the uarg, such as MSG_ZEROCOPY. This
uarg is only ever completed from skb_zcopy_clear, so skb is always set.

To prevent userspace from aliasing in-flight state on shared ring
slots, allocate tpacket_uarg per packet, rather than per slot. This
adds a small allocation to the transmit path. Use standard kmalloc to
allow backporting to stable kernels.

The uarg holds an sk_wmem_alloc reference, rather than an sk_refcnt
reference. packet_free_tx_ring waits on sk_wmem_alloc before freeing
the ring pages. Always allocate vec->deferred for tx_ring so page-backed
rings also wait on sk_wmem_alloc when skb_copy_ubufs drops page refs
before calling tpacket_ubuf_complete.

Drop the tx_ring.pg_vec test that tpacket_destruct_skb performed before
accessing the slot. The sk_wmem_alloc reference now guarantees that the
slot is valid. The test is also not sufficient by itself, as it reads
pg_vec without pg_vec_lock, so it can race with packet_set_ring.

As a result a slot is released when its payload is copied, which can
be before transmission (e.g., in skb_orphan_frags_rx). If copied
before skb_tx_timestamp() is called, no slot timestamp is recorded,
similar to when skb_orphan() was called early in the datapath before
this patch.

Revert the now unused previous skb_zcopy_.._nouarg infra.

Depends on commit 992cc9f94ca9 ("net/packet: defer vmalloc TX_RING
free until skbs finish").

Reported-by: Katherine Leaver <kleaver@janestreet.com>
Reported-by: Bjoern Doebel <doebel@amazon.de>
Closes: https://lore.kernel.org/netdev/20260909085542.3370986-1-doebel@amazon.de/
Fixes: 5cd8d46ea156 ("packet: copy user buffers before orphan or clone")
Cc: stable@vger.kernel.org
Signed-off-by: Willem de Bruijn <willemb@google.com>

---

v1->v2
  - Always allocate vec->deferred for tx_ring so page-backed rings also
    defer freeing until sk_wmem_alloc drops to zero
  - Clarify in commit message that copying before skb_tx_timestamp()
    omits slot timestamp
  - Drop the unreachable NULL skb test in tpacket_ubuf_complete, in
    favor of DEBUG_NET_WARN_ON_ONCE
  - Drop the tx_ring.pg_vec test in tpacket_ubuf_complete: neither
    needed nor synchronized

Verified with tools/testing/selftests/net/txring_overwrite and the RPS
setup from Bjoern's report.

---
 include/linux/skbuff.h |  19 +-------
 net/packet/af_packet.c | 102 ++++++++++++++++++++++++++---------------
 2 files changed, 65 insertions(+), 56 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 421f6fc45451..b14d6be7370b 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1834,22 +1834,6 @@ static inline void skb_zcopy_set(struct sk_buff *skb, struct ubuf_info *uarg,
 	}
 }
 
-static inline void skb_zcopy_set_nouarg(struct sk_buff *skb, void *val)
-{
-	skb_shinfo(skb)->destructor_arg = (void *)((uintptr_t) val | 0x1UL);
-	skb_shinfo(skb)->flags |= SKBFL_ZEROCOPY_FRAG;
-}
-
-static inline bool skb_zcopy_is_nouarg(struct sk_buff *skb)
-{
-	return (uintptr_t) skb_shinfo(skb)->destructor_arg & 0x1UL;
-}
-
-static inline void *skb_zcopy_get_nouarg(struct sk_buff *skb)
-{
-	return (void *)((uintptr_t) skb_shinfo(skb)->destructor_arg & ~0x1UL);
-}
-
 static inline void net_zcopy_put(struct ubuf_info *uarg)
 {
 	if (uarg)
@@ -1872,8 +1856,7 @@ static inline void skb_zcopy_clear(struct sk_buff *skb, bool zerocopy_success)
 	struct ubuf_info *uarg = skb_zcopy(skb);
 
 	if (uarg) {
-		if (!skb_zcopy_is_nouarg(skb))
-			uarg->ops->complete(skb, uarg, zerocopy_success);
+		uarg->ops->complete(skb, uarg, zerocopy_success);
 
 		skb_shinfo(skb)->flags &= ~SKBFL_ALL_ZEROCOPY;
 	}
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 76bde7906d49..fba81036635b 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2528,26 +2528,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
 	goto drop_n_restore;
 }
 
-static void tpacket_destruct_skb(struct sk_buff *skb)
-{
-	struct packet_sock *po = pkt_sk(skb->sk);
-
-	if (likely(po->tx_ring.pg_vec)) {
-		void *ph;
-		__u32 ts;
-
-		ph = skb_zcopy_get_nouarg(skb);
-
-		ts = __packet_set_timestamp(po, ph, skb);
-		__packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts);
-
-		packet_dec_pending(&po->tx_ring);
-		complete(&po->skb_completion);
-	}
-
-	sock_wfree(skb);
-}
-
 static int __packet_snd_vnet_parse(struct virtio_net_hdr *vnet_hdr, size_t len)
 {
 	if ((vnet_hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
@@ -2587,27 +2567,56 @@ static int packet_snd_vnet_parse(struct msghdr *msg, size_t *len,
 	return 0;
 }
 
+struct tpacket_uarg {
+	struct ubuf_info	ubuf;
+	struct packet_sock	*po;
+	void			*ph;
+};
+
+static void tpacket_ubuf_complete(struct sk_buff *skb, struct ubuf_info *uarg,
+				  bool success)
+{
+	struct tpacket_uarg *tu = container_of(uarg, struct tpacket_uarg, ubuf);
+	struct packet_sock *po = tu->po;
+	void *ph = tu->ph;
+	__u32 ts;
+
+	DEBUG_NET_WARN_ON_ONCE(!skb);
+
+	if (!refcount_dec_and_test(&uarg->refcnt))
+		return;
+
+	ts = __packet_set_timestamp(po, ph, skb);
+	__packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts);
+
+	packet_dec_pending(&po->tx_ring);
+	complete(&po->skb_completion);
+
+	kfree(tu);
+	sk_free(&po->sk);
+}
+
+static const struct ubuf_info_ops tpacket_ubuf_ops = {
+	.complete = tpacket_ubuf_complete,
+};
+
 static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
-		void *frame, struct net_device *dev, void *data, int tp_len,
+		struct net_device *dev, void *data, int tp_len,
 		__be16 proto, unsigned char *addr, int hlen, int copylen,
 		int hard_header_len,
 		const struct sockcm_cookie *sockc)
 {
-	union tpacket_uhdr ph;
 	int to_write, offset, len, nr_frags, len_max;
 	struct socket *sock = po->sk.sk_socket;
 	struct page *page;
 	int err;
 
-	ph.raw = frame;
-
 	skb->protocol = proto;
 	skb->dev = dev;
 	skb->priority = sockc->priority;
 	skb->mark = sockc->mark;
 	skb_set_delivery_type_by_clockid(skb, sockc->transmit_time, po->sk.sk_clockid);
 	skb_setup_tx_timestamp(skb, sockc);
-	skb_zcopy_set_nouarg(skb, ph.raw);
 
 	skb_reserve(skb, hlen);
 	skb_reset_network_header(skb);
@@ -2747,6 +2756,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 	struct virtio_net_hdr vnet_hdr;
 	bool has_vnet_hdr = false;
 	struct sockcm_cookie sockc;
+	struct tpacket_uarg *uarg;
 	__be16 proto;
 	int err, reserve = 0;
 	void *ph;
@@ -2874,7 +2884,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 				err = len_sum;
 			goto out_status;
 		}
-		tp_len = tpacket_fill_skb(po, skb, ph, dev, data, tp_len, proto,
+		tp_len = tpacket_fill_skb(po, skb, dev, data, tp_len, proto,
 					  addr, hlen, copylen, hard_header_len,
 					  &sockc);
 		if (likely(tp_len >= 0) &&
@@ -2906,7 +2916,24 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 			virtio_net_hdr_set_proto(skb, &vnet_hdr);
 		}
 
-		skb->destructor = tpacket_destruct_skb;
+		uarg = kmalloc(sizeof(*uarg), GFP_KERNEL);
+		if (unlikely(!uarg)) {
+			if (likely(len_sum > 0))
+				err = len_sum;
+			else
+				err = -ENOMEM;
+			goto out_status;
+		}
+		uarg->po = po;
+		uarg->ph = ph;
+		uarg->ubuf.ops = &tpacket_ubuf_ops;
+		uarg->ubuf.flags = SKBFL_ZEROCOPY_FRAG;
+		refcount_set(&uarg->ubuf.refcnt, 1);
+
+		/* Hold a sk_wmem_alloc reference until completion */
+		refcount_inc(&po->sk.sk_wmem_alloc);
+		skb_zcopy_init(skb, &uarg->ubuf);
+
 		__packet_set_status(po, ph, TP_STATUS_SENDING);
 		packet_inc_pending(&po->tx_ring);
 
@@ -4484,21 +4511,20 @@ static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order, bool tx_ring
 	vec->len = block_nr;
 	pg_vec = vec->pg_vec;
 
+	if (tx_ring) {
+		vec->deferred = kzalloc_obj(*vec->deferred,
+					    GFP_KERNEL | __GFP_NOWARN);
+		if (!vec->deferred)
+			goto out_free_pgvec;
+		vec->deferred->vec = vec;
+		INIT_DELAYED_WORK(&vec->deferred->work,
+				  packet_free_pg_vec_work);
+	}
+
 	for (i = 0; i < block_nr; i++) {
 		pg_vec[i].buffer = alloc_one_pg_vec_page(order);
 		if (unlikely(!pg_vec[i].buffer))
 			goto out_free_pgvec;
-
-		if (tx_ring && !vec->deferred &&
-		    is_vmalloc_addr(pg_vec[i].buffer)) {
-			vec->deferred = kzalloc_obj(*vec->deferred,
-						    GFP_KERNEL | __GFP_NOWARN);
-			if (!vec->deferred)
-				goto out_free_pgvec;
-			vec->deferred->vec = vec;
-			INIT_DELAYED_WORK(&vec->deferred->work,
-					  packet_free_pg_vec_work);
-		}
 	}
 
 out:
-- 
2.55.0.1082.g2b9226bbc0-goog


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

* Re: [PATCH net v2 1/2] virtio_net: copy zerocopy frags in start_xmit without NAPI
  2026-09-19  0:47 ` [PATCH net v2 1/2] virtio_net: copy zerocopy frags in start_xmit without NAPI Willem de Bruijn
@ 2026-09-22  3:49   ` netdev-bot+sashiko
  2026-09-22 15:01     ` Willem de Bruijn
  0 siblings, 1 reply; 8+ messages in thread
From: netdev-bot+sashiko @ 2026-09-22  3:49 UTC (permalink / raw)
  To: willemdebruijn.kernel
  Cc: netdev, davem, kuba, edumazet, pabeni, horms, andrew+netdev,
	willemb, kleaver, doebel, stable

Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider.

Critical: 0 · High: 0 · Medium: 1 · Low: 0 (1)

If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).

- [Medium] Commit message mischaracterizes the defect being fixed, which
  matters because the patch carries Fixes: 5cd8d46ea156 and Cc: stable.

Pre-existing issues:
- [Low] This problem wasn't introduced by this patch, but after it
  start_xmit() contains two logically identical drop-and-return-…

--

virtio_net: copy zerocopy frags in start_xmit without NAPI

When napi_tx is disabled, start_xmit() now calls skb_orphan_frags() before
transmitting, so zerocopy frags that do not set SKBFL_DONT_ORPHAN are deep
copied instead of being handed to the virtqueue and then orphaned. On copy
failure the skb is dropped, counted in tx_dropped, and the new kick_vq label
is used so a pending xmit_more batch is still flushed.

A couple of questions below.

> virtio_net: copy zerocopy frags in start_xmit without NAPI
>
> Virtio-net without NAPI frees completed skbs lazily on the next
> start_xmit. Senders waiting for in-flight zerocopy buffers can
> deadlock if they cannot transmit more packets, as then no
> completed packets will be freed.
[ ... ]
> This fixes the tpacket_snd slot reuse bug on skb_orphan for
> virtio-net, and prevents PACKET_TX_RING from running out of slots.

[Severity: Medium]
Does the leading description match the tree this patch applies to?  The
patch carries a Fixes: tag and Cc: stable, so the described failure mode is
what a backporter will look for.

In the current tree, tpacket_snd() installs a destructor:

net/packet/af_packet.c:tpacket_snd() {
	...
	skb->destructor = tpacket_destruct_skb;
	...
}

and that destructor releases the slot, drops the pending count and completes
the waiter:

net/packet/af_packet.c:tpacket_destruct_skb() {
	...
		__packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts);
		packet_dec_pending(&po->tx_ring);
		complete(&po->skb_completion);
	...
}

The pre-existing skb_orphan() in start_xmit() for !use_napi runs that
destructor within the same start_xmit() call, so the slot is returned
immediately.  Given that, can a PACKET_TX_RING sender actually run out of
slots or block in wait_for_completion_interruptible_timeout() before this
series?

The clause about "the tpacket_snd slot reuse bug on skb_orphan" looks like
the defect that exists today, and it is the opposite of exhaustion: because
skb_orphan() runs after xmit_skb() has already linked the ring pages into
the virtqueue, the slot is marked available to userspace while the device may
still be reading those pages.  That is silent payload corruption rather than
a stall.

The deadlock and slot-exhaustion wording appears to apply only after the
follow-up patch that converts PACKET_TX_RING to ubuf_info completion and
removes tpacket_destruct_skb().  Could the message lead with the
data-corruption case for the current tree, and keep the deadlock argument
scoped to the follow-up patch?

> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index e34c52d059d3..bf82ef9874ab 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -3349,6 +3349,14 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
>  	else
>  		virtqueue_disable_cb(sq->vq);
>  
> +	if (!use_napi &&
> +	    unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) {
> +		DEV_STATS_INC(dev, tx_dropped);
> +		dev_kfree_skb_any(skb);
> +		kick = !xmit_more || netif_xmit_stopped(txq);
> +		goto kick_vq;
> +	}
> +

[Severity: Low]
This isn't a bug introduced by this patch, but the new drop path and the
existing xmit_skb() failure drop path in start_xmit() now disagree on the
kick protocol.  The new path computes kick and goes to kick_vq, while the
older one returns directly:

drivers/net/virtio_net.c:start_xmit() {
	...
	err = xmit_skb(sq, skb, !use_napi);

	/* This should not happen! */
	if (unlikely(err)) {
		DEV_STATS_INC(dev, tx_fifo_errors);
		...
		DEV_STATS_INC(dev, tx_dropped);
		dev_kfree_skb_any(skb);
		return NETDEV_TX_OK;
	}
	...
}

If xmit_skb() returns an error such as -ENOMEM from the indirect descriptor
allocation on the last packet of an xmit_more batch, do the descriptors
already added by the earlier packets of that batch stay un-notified until
some later start_xmit() on the same send queue computes kick = true?  The
-ENOSPC case is covered because check_sq_full_and_disable() stops the txq and
netif_xmit_stopped(txq) then forces a kick.

Would it make sense to route the xmit_skb() failure path through the new
kick_vq label as well, so both drops behave the same?

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260919004748.1463985-1-willemdebruijn.kernel%40gmail.com

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

* Re: [PATCH net v2 2/2] packet: use ubuf_info completion for TX_RING packets
  2026-09-19  0:47 ` [PATCH net v2 2/2] packet: use ubuf_info completion for TX_RING packets Willem de Bruijn
@ 2026-09-22  3:49   ` netdev-bot+sashiko
  2026-09-22 15:07     ` Willem de Bruijn
  0 siblings, 1 reply; 8+ messages in thread
From: netdev-bot+sashiko @ 2026-09-22  3:49 UTC (permalink / raw)
  To: willemdebruijn.kernel
  Cc: netdev, davem, kuba, edumazet, pabeni, horms, andrew+netdev,
	willemb, kleaver, doebel, stable

Thank you for your contribution! Sashiko AI review found 3 potential
issue(s) to consider.

Critical: 0 · High: 0 · Medium: 2 · Low: 1

If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).

- [Medium] The new per-packet `sk_wmem_alloc` charge taken in
  tpacket_snd() (`refcount_inc(&po->sk.sk_wmem_alloc)` at…
- [Medium] Documentation/networking/packet_mmap.rst still describes the
  old TX_RING contract that this patch changes.
- [Low] tpacket_snd() still carries the comments `/* skb was destructed
  already */` (net/packet/af_packet.c:2949) and `/* skb was dropped but…

--

packet: use ubuf_info completion for TX_RING packets

This converts tpacket_snd() from a custom skb->destructor
(tpacket_destruct_skb) to standard zerocopy completion, so a TX_RING slot
is only released once all references to the payload are gone or copied.
The uarg is allocated per packet and holds an sk_wmem_alloc reference, and
the now unused skb_zcopy_*_nouarg helpers are removed.

Closes: https://lore.kernel.org/netdev/20260909085542.3370986-1-doebel@amazon.de/

> diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
> index 50cae32ae269..64b501db660a 100644
> --- a/net/packet/af_packet.c
> +++ b/net/packet/af_packet.c
> @@ -2530,26 +2530,6 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
>  	goto drop_n_restore;
>  }
>  
> -static void tpacket_destruct_skb(struct sk_buff *skb)
> -{
> -	struct packet_sock *po = pkt_sk(skb->sk);
> -
> -	if (likely(po->tx_ring.pg_vec)) {
> -		void *ph;
> -		__u32 ts;
> -
> -		ph = skb_zcopy_get_nouarg(skb);
> -
> -		ts = __packet_set_timestamp(po, ph, skb);
> -		__packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts);
> -
> -		packet_dec_pending(&po->tx_ring);
> -		complete(&po->skb_completion);
> -	}
> -
> -	sock_wfree(skb);
> -}
> -

[ ... ]

> @@ -2589,27 +2569,56 @@ static int packet_snd_vnet_parse(struct msghdr *msg, size_t *len,
>  	return 0;
>  }
>  
> +struct tpacket_uarg {
> +	struct ubuf_info	ubuf;
> +	struct packet_sock	*po;
> +	void			*ph;
> +};
> +
> +static void tpacket_ubuf_complete(struct sk_buff *skb, struct ubuf_info *uarg,
> +				  bool success)
> +{
> +	struct tpacket_uarg *tu = container_of(uarg, struct tpacket_uarg, ubuf);
> +	struct packet_sock *po = tu->po;
> +	void *ph = tu->ph;
> +	__u32 ts;
> +
> +	DEBUG_NET_WARN_ON_ONCE(!skb);
> +
> +	if (!refcount_dec_and_test(&uarg->refcnt))
> +		return;
> +
> +	ts = __packet_set_timestamp(po, ph, skb);
> +	__packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts);

[Severity: Medium]
Should Documentation/networking/packet_mmap.rst be updated along with this
change?  The "Transmission process" section still says:

  The kernel updates each status of sent frames with TP_STATUS_SENDING
  until the end of transfer.

  At the end of each transfer, buffer status returns to
  TP_STATUS_AVAILABLE.

With slot release moved into tpacket_ubuf_complete(), TP_STATUS_AVAILABLE
now means "the kernel no longer references the payload", which the commit
message says can happen before transmission:

  net/core/dev.c:deliver_skb()
    skb_orphan_frags_rx()
      skb_copy_ubufs()
        skb_zcopy_clear()
          tpacket_ubuf_complete()

The timestamp section also documents a specific recipe:

  Getting timestamps for the TX_RING works as follows: i) fill the ring
  frames, ii) call sendto() e.g. in blocking mode, iii) wait for status of
  relevant frames to be updated resp. the frame handed over to the
  application, iv) walk through the frames to pick up the individual hw/sw
  timestamps.

When the copy happens before skb_tx_timestamp(),
__packet_set_timestamp() returns 0, so the frame is handed back as
TP_STATUS_AVAILABLE with no TP_STATUS_TS_* bit and stale tp_sec/tp_nsec,
even though timestamping was requested.  Can that documented procedure
still be followed, or should the text describe the new semantics?

> +
> +	packet_dec_pending(&po->tx_ring);
> +	complete(&po->skb_completion);
> +
> +	kfree(tu);
> +	sk_free(&po->sk);
> +}

[Severity: Medium]
Does releasing the wmem charge through sk_free() here miss a write space
notification?

sk_free() only does the decrement:

net/core/sock.c:sk_free() {
	if (refcount_dec_and_test(&sk->sk_wmem_alloc))
		__sk_free(sk);
}

whereas the skb charge release path notifies first:

net/core/sock.c:sock_wfree() {
	...
		WARN_ON(refcount_sub_and_test(len - 1, &sk->sk_wmem_alloc));
		sk_write_space(sk);
		len = 1;
	...
}

A blocking TX_RING sender reaches sock_wait_for_wmem() via
tpacket_snd()->sock_alloc_send_skb()->sock_alloc_send_pskb(), and its only
wake condition for send space is sk->sk_write_space():

net/core/sock.c:sock_wait_for_wmem() {
	...
		if (refcount_read(&sk->sk_wmem_alloc) < READ_ONCE(sk->sk_sndbuf))
			break;
		...
		timeo = schedule_timeout(timeo);
	...
}

With the default sk_sndtimeo that schedule_timeout() is
MAX_SCHEDULE_TIMEOUT.  If the drop below sk_sndbuf is performed by the new
uarg charges only, is anything left to wake the sleeper?  A path where the
skb charge is gone while the uarg charge is still outstanding is
loopback_xmit(), which calls skb_orphan(skb) (running sock_wfree) without
skb_orphan_frags(), so the ubuf_info survives in the backlog.

[ ... ]

> @@ -2908,7 +2918,24 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
>  			virtio_net_hdr_set_proto(skb, &vnet_hdr);
>  		}
>  
> -		skb->destructor = tpacket_destruct_skb;
> +		uarg = kmalloc(sizeof(*uarg), GFP_KERNEL);
> +		if (unlikely(!uarg)) {
> +			if (likely(len_sum > 0))
> +				err = len_sum;
> +			else
> +				err = -ENOMEM;
> +			goto out_status;
> +		}
> +		uarg->po = po;
> +		uarg->ph = ph;
> +		uarg->ubuf.ops = &tpacket_ubuf_ops;
> +		uarg->ubuf.flags = SKBFL_ZEROCOPY_FRAG;
> +		refcount_set(&uarg->ubuf.refcnt, 1);
> +
> +		/* Hold a sk_wmem_alloc reference until completion */
> +		refcount_inc(&po->sk.sk_wmem_alloc);
> +		skb_zcopy_init(skb, &uarg->ubuf);
> +
>  		__packet_set_status(po, ph, TP_STATUS_SENDING);
>  		packet_inc_pending(&po->tx_ring);
>  

[Severity: Low]
Just below this, the packet_xmit() error handling in tpacket_snd() still
refers to the destructor that this patch removes:

net/packet/af_packet.c:tpacket_snd() {
	...
			if (err && __packet_get_status(po, ph) ==
				   TP_STATUS_AVAILABLE) {
				/* skb was destructed already */
				skb = NULL;
				goto out_status;
			}
			/*
			 * skb was dropped but not destructed yet;
			 * let's treat it like congestion or err < 0
			 */
	...
}

With skb->destructor back to sock_wfree and slot release moved to
tpacket_ubuf_complete(), does the slot status still imply anything about
the skb?  TP_STATUS_AVAILABLE can now be observed while the skb is alive
(the uarg completed early through skb_copy_ubufs()), and the slot can
still read TP_STATUS_SENDING after the skb was freed if a clone or segment
holds an extra uarg reference.  Should these comments be reworded for the
new completion scheme?

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260919004748.1463985-1-willemdebruijn.kernel%40gmail.com

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

* Re: [PATCH net v2 1/2] virtio_net: copy zerocopy frags in start_xmit without NAPI
  2026-09-22  3:49   ` netdev-bot+sashiko
@ 2026-09-22 15:01     ` Willem de Bruijn
  0 siblings, 0 replies; 8+ messages in thread
From: Willem de Bruijn @ 2026-09-22 15:01 UTC (permalink / raw)
  To: netdev-bot+sashiko, willemdebruijn.kernel
  Cc: netdev, davem, kuba, edumazet, pabeni, horms, andrew+netdev,
	willemb, kleaver, doebel, stable

netdev-bot+sashiko@ wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue(s) to consider.
> 
> Critical: 0 · High: 0 · Medium: 1 · Low: 0 (1)
> 
> If you believe none of the issues are legitimate, please reply to each
> issue of Medium severity or higher and explain why the AI is wrong.
> If any of them are legitimate and you plan to respin, please let patchwork
> know by including "pw-bot: cr" as a separate line at the end of your reply
> (one such reply per series is enough).
> 
> - [Medium] Commit message mischaracterizes the defect being fixed, which
>   matters because the patch carries Fixes: 5cd8d46ea156 and Cc: stable.
> 
> Pre-existing issues:
> - [Low] This problem wasn't introduced by this patch, but after it
>   start_xmit() contains two logically identical drop-and-return-…
> 
> --
> 
> virtio_net: copy zerocopy frags in start_xmit without NAPI
> 
> When napi_tx is disabled, start_xmit() now calls skb_orphan_frags() before
> transmitting, so zerocopy frags that do not set SKBFL_DONT_ORPHAN are deep
> copied instead of being handed to the virtqueue and then orphaned. On copy
> failure the skb is dropped, counted in tx_dropped, and the new kick_vq label
> is used so a pending xmit_more batch is still flushed.
> 
> A couple of questions below.
> 
> > virtio_net: copy zerocopy frags in start_xmit without NAPI
> >
> > Virtio-net without NAPI frees completed skbs lazily on the next
> > start_xmit. Senders waiting for in-flight zerocopy buffers can
> > deadlock if they cannot transmit more packets, as then no
> > completed packets will be freed.
> [ ... ]
> > This fixes the tpacket_snd slot reuse bug on skb_orphan for
> > virtio-net, and prevents PACKET_TX_RING from running out of slots.
> 
> [Severity: Medium]
> Does the leading description match the tree this patch applies to?  The
> patch carries a Fixes: tag and Cc: stable, so the described failure mode is
> what a backporter will look for.
> 
> In the current tree, tpacket_snd() installs a destructor:
> 
> net/packet/af_packet.c:tpacket_snd() {
> 	...
> 	skb->destructor = tpacket_destruct_skb;
> 	...
> }
> 
> and that destructor releases the slot, drops the pending count and completes
> the waiter:
> 
> net/packet/af_packet.c:tpacket_destruct_skb() {
> 	...
> 		__packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts);
> 		packet_dec_pending(&po->tx_ring);
> 		complete(&po->skb_completion);
> 	...
> }
> 
> The pre-existing skb_orphan() in start_xmit() for !use_napi runs that
> destructor within the same start_xmit() call, so the slot is returned
> immediately.  Given that, can a PACKET_TX_RING sender actually run out of
> slots or block in wait_for_completion_interruptible_timeout() before this
> series?
> 
> The clause about "the tpacket_snd slot reuse bug on skb_orphan" looks like
> the defect that exists today, and it is the opposite of exhaustion: because
> skb_orphan() runs after xmit_skb() has already linked the ring pages into
> the virtqueue, the slot is marked available to userspace while the device may
> still be reading those pages.  That is silent payload corruption rather than
> a stall.
> 
> The deadlock and slot-exhaustion wording appears to apply only after the
> follow-up patch that converts PACKET_TX_RING to ubuf_info completion and
> removes tpacket_destruct_skb().  Could the message lead with the
> data-corruption case for the current tree, and keep the deadlock argument
> scoped to the follow-up patch?

[Medium] the request is only to change the emphasis of the wording
of the commit message. No code changes suggested:

Focus more on the data corruption bug and less on the deadlock that
can occur when not releasing the slots prematurely (that data
corruption).

See this statement in the commit

  This fixes the tpacket_snd slot reuse bug on skb_orphan for
  virtio-net, and prevents PACKET_TX_RING from running out of slots.

Maybe it should be moved up and say "while preventing".

Seems a bit of a pedantic comment to me, honestly.

I will reword if the other patch requires a respin, but this does not
warrant one on its own imho.

> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index e34c52d059d3..bf82ef9874ab 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -3349,6 +3349,14 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
> >  	else
> >  		virtqueue_disable_cb(sq->vq);
> >  
> > +	if (!use_napi &&
> > +	    unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) {
> > +		DEV_STATS_INC(dev, tx_dropped);
> > +		dev_kfree_skb_any(skb);
> > +		kick = !xmit_more || netif_xmit_stopped(txq);
> > +		goto kick_vq;
> > +	}
> > +
> 
> [Severity: Low]
> This isn't a bug introduced by this patch, but the new drop path and the
> existing xmit_skb() failure drop path in start_xmit() now disagree on the
> kick protocol.  The new path computes kick and goes to kick_vq, while the
> older one returns directly:
> 
> drivers/net/virtio_net.c:start_xmit() {
> 	...
> 	err = xmit_skb(sq, skb, !use_napi);
> 
> 	/* This should not happen! */
> 	if (unlikely(err)) {
> 		DEV_STATS_INC(dev, tx_fifo_errors);
> 		...
> 		DEV_STATS_INC(dev, tx_dropped);
> 		dev_kfree_skb_any(skb);
> 		return NETDEV_TX_OK;
> 	}
> 	...
> }
> 
> If xmit_skb() returns an error such as -ENOMEM from the indirect descriptor
> allocation on the last packet of an xmit_more batch, do the descriptors
> already added by the earlier packets of that batch stay un-notified until
> some later start_xmit() on the same send queue computes kick = true?  The
> -ENOSPC case is covered because check_sq_full_and_disable() stops the txq and
> netif_xmit_stopped(txq) then forces a kick.
> 
> Would it make sense to route the xmit_skb() failure path through the new
> kick_vq label as well, so both drops behave the same?

[Low] but I'll respond: pre-existing issue is out of scope here. But
probably makes sense as a separate fix.

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

* Re: [PATCH net v2 2/2] packet: use ubuf_info completion for TX_RING packets
  2026-09-22  3:49   ` netdev-bot+sashiko
@ 2026-09-22 15:07     ` Willem de Bruijn
  0 siblings, 0 replies; 8+ messages in thread
From: Willem de Bruijn @ 2026-09-22 15:07 UTC (permalink / raw)
  To: netdev-bot+sashiko, willemdebruijn.kernel
  Cc: netdev, davem, kuba, edumazet, pabeni, horms, andrew+netdev,
	willemb, kleaver, doebel, stable

netdev-bot+sashiko@ wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential
> issue(s) to consider.
> 
> Critical: 0 · High: 0 · Medium: 2 · Low: 1
> 

> [Severity: Medium]
> Should Documentation/networking/packet_mmap.rst be updated along with this
> change?  The "Transmission process" section still says:
> 
>   The kernel updates each status of sent frames with TP_STATUS_SENDING
>   until the end of transfer.
> 
>   At the end of each transfer, buffer status returns to
>   TP_STATUS_AVAILABLE.
> 
> With slot release moved into tpacket_ubuf_complete(), TP_STATUS_AVAILABLE
> now means "the kernel no longer references the payload", which the commit
> message says can happen before transmission:
> 
>   net/core/dev.c:deliver_skb()
>     skb_orphan_frags_rx()
>       skb_copy_ubufs()
>         skb_zcopy_clear()
>           tpacket_ubuf_complete()

[Medium] This is a pre-existing issue.

The slot can be returned prior to the end of transfer after this
change. But the same was true before this change with skb_orphan().

I can improve this documentation in a follow-up to net-next. But I
don't think it belongs in a stable patch.

> 
> The timestamp section also documents a specific recipe:
> 
>   Getting timestamps for the TX_RING works as follows: i) fill the ring
>   frames, ii) call sendto() e.g. in blocking mode, iii) wait for status of
>   relevant frames to be updated resp. the frame handed over to the
>   application, iv) walk through the frames to pick up the individual hw/sw
>   timestamps.
> 
> When the copy happens before skb_tx_timestamp(),
> __packet_set_timestamp() returns 0, so the frame is handed back as
> TP_STATUS_AVAILABLE with no TP_STATUS_TS_* bit and stale tp_sec/tp_nsec,
> even though timestamping was requested.  Can that documented procedure
> still be followed, or should the text describe the new semantics?
> 
> > +
> > +	packet_dec_pending(&po->tx_ring);
> > +	complete(&po->skb_completion);
> > +
> > +	kfree(tu);
> > +	sk_free(&po->sk);
> > +}
> 
> [Severity: Medium]
> Does releasing the wmem charge through sk_free() here miss a write space
> notification?
> 
> sk_free() only does the decrement:
> 
> net/core/sock.c:sk_free() {
> 	if (refcount_dec_and_test(&sk->sk_wmem_alloc))
> 		__sk_free(sk);
> }
> 
> whereas the skb charge release path notifies first:
> 
> net/core/sock.c:sock_wfree() {
> 	...
> 		WARN_ON(refcount_sub_and_test(len - 1, &sk->sk_wmem_alloc));
> 		sk_write_space(sk);
> 		len = 1;
> 	...
> }

[Medium] False positive.

This sk_free only releases a 1 byte hold for the slot.

The actual release of the truesize attributed to the data (to_write)
is released in the normal sock_wfree path.

It is admittedly odd to have two wmem operations per slot. And perhaps
even questionable to have truesize and wmem count userspace TX_RING
data. But the second is pre-existing and for net-next.

The first is new, but alternatives like sock_hold were found to be
less preferable than an extra 1B hold on wmem.

> 
> A blocking TX_RING sender reaches sock_wait_for_wmem() via
> tpacket_snd()->sock_alloc_send_skb()->sock_alloc_send_pskb(), and its only
> wake condition for send space is sk->sk_write_space():
> 
> net/core/sock.c:sock_wait_for_wmem() {
> 	...
> 		if (refcount_read(&sk->sk_wmem_alloc) < READ_ONCE(sk->sk_sndbuf))
> 			break;
> 		...
> 		timeo = schedule_timeout(timeo);
> 	...
> }
> 
> With the default sk_sndtimeo that schedule_timeout() is
> MAX_SCHEDULE_TIMEOUT.  If the drop below sk_sndbuf is performed by the new
> uarg charges only, is anything left to wake the sleeper?  A path where the
> skb charge is gone while the uarg charge is still outstanding is
> loopback_xmit(), which calls skb_orphan(skb) (running sock_wfree) without
> skb_orphan_frags(), so the ubuf_info survives in the backlog.
> 
> [ ... ]
> 
> > @@ -2908,7 +2918,24 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
> >  			virtio_net_hdr_set_proto(skb, &vnet_hdr);
> >  		}
> >  
> > -		skb->destructor = tpacket_destruct_skb;
> > +		uarg = kmalloc(sizeof(*uarg), GFP_KERNEL);
> > +		if (unlikely(!uarg)) {
> > +			if (likely(len_sum > 0))
> > +				err = len_sum;
> > +			else
> > +				err = -ENOMEM;
> > +			goto out_status;
> > +		}
> > +		uarg->po = po;
> > +		uarg->ph = ph;
> > +		uarg->ubuf.ops = &tpacket_ubuf_ops;
> > +		uarg->ubuf.flags = SKBFL_ZEROCOPY_FRAG;
> > +		refcount_set(&uarg->ubuf.refcnt, 1);
> > +
> > +		/* Hold a sk_wmem_alloc reference until completion */
> > +		refcount_inc(&po->sk.sk_wmem_alloc);
> > +		skb_zcopy_init(skb, &uarg->ubuf);
> > +
> >  		__packet_set_status(po, ph, TP_STATUS_SENDING);
> >  		packet_inc_pending(&po->tx_ring);
> >  
> 
> [Severity: Low]
> Just below this, the packet_xmit() error handling in tpacket_snd() still
> refers to the destructor that this patch removes:
> 
> net/packet/af_packet.c:tpacket_snd() {
> 	...
> 			if (err && __packet_get_status(po, ph) ==
> 				   TP_STATUS_AVAILABLE) {
> 				/* skb was destructed already */
> 				skb = NULL;
> 				goto out_status;
> 			}
> 			/*
> 			 * skb was dropped but not destructed yet;
> 			 * let's treat it like congestion or err < 0
> 			 */
> 	...
> }
> 
> With skb->destructor back to sock_wfree and slot release moved to
> tpacket_ubuf_complete(), does the slot status still imply anything about
> the skb?  TP_STATUS_AVAILABLE can now be observed while the skb is alive
> (the uarg completed early through skb_copy_ubufs()), and the slot can
> still read TP_STATUS_SENDING after the skb was freed if a clone or segment
> holds an extra uarg reference.  Should these comments be reworded for the
> new completion scheme?
> 
> -- 
> Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260919004748.1463985-1-willemdebruijn.kernel%40gmail.com



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

* Re: [PATCH net v2 0/2] packet: fix PACKET_TX_RING data corruption on skb_orphan
  2026-09-19  0:47 [PATCH net v2 0/2] packet: fix PACKET_TX_RING data corruption on skb_orphan Willem de Bruijn
  2026-09-19  0:47 ` [PATCH net v2 1/2] virtio_net: copy zerocopy frags in start_xmit without NAPI Willem de Bruijn
  2026-09-19  0:47 ` [PATCH net v2 2/2] packet: use ubuf_info completion for TX_RING packets Willem de Bruijn
@ 2026-09-23  2:00 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 8+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-09-23  2:00 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: netdev, davem, kuba, edumazet, pabeni, horms, andrew+netdev,
	willemb

Hello:

This series was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:

On Fri, 18 Sep 2026 20:47:27 -0400 you wrote:
> From: Willem de Bruijn <willemb@google.com>
> 
> When transmitting packets via PACKET_TX_RING, tpacket_snd links user
> ring buffer pages as skb frags and releases the slot on skb->destructor
> (tpacket_destruct_skb).
> 
> skb_orphan() invokes the destructor while the skb is still alive.
> This marks the slot as TP_STATUS_AVAILABLE prematurely, allowing
> userspace to overwrite the slot and causing data corruption.
> 
> [...]

Here is the summary with links:
  - [net,v2,1/2] virtio_net: copy zerocopy frags in start_xmit without NAPI
    https://git.kernel.org/netdev/net/c/07e1a9408b6c
  - [net,v2,2/2] packet: use ubuf_info completion for TX_RING packets
    https://git.kernel.org/netdev/net/c/951840561386

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2026-09-23  2:01 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-19  0:47 [PATCH net v2 0/2] packet: fix PACKET_TX_RING data corruption on skb_orphan Willem de Bruijn
2026-09-19  0:47 ` [PATCH net v2 1/2] virtio_net: copy zerocopy frags in start_xmit without NAPI Willem de Bruijn
2026-09-22  3:49   ` netdev-bot+sashiko
2026-09-22 15:01     ` Willem de Bruijn
2026-09-19  0:47 ` [PATCH net v2 2/2] packet: use ubuf_info completion for TX_RING packets Willem de Bruijn
2026-09-22  3:49   ` netdev-bot+sashiko
2026-09-22 15:07     ` Willem de Bruijn
2026-09-23  2:00 ` [PATCH net v2 0/2] packet: fix PACKET_TX_RING data corruption on skb_orphan patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox