All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	patches@lists.linux.dev, Eric Dumazet <edumazet@google.com>,
	Willem de Bruijn <willemdebruijn.kernel@gmail.com>,
	Willem de Bruijn <willemb@google.com>,
	Kyle Zeng <kylebot@openai.com>, Jakub Kicinski <kuba@kernel.org>
Subject: [PATCH 7.2 41/71] net/packet: defer vmalloc TX_RING free until skbs finish
Date: Mon, 31 Aug 2026 15:34:06 +0200	[thread overview]
Message-ID: <20260831133401.339016743@linuxfoundation.org> (raw)
In-Reply-To: <20260831133359.055927882@linuxfoundation.org>

7.2-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Kyle Zeng <kylebot@openai.com>

commit 992cc9f94ca924089a506ba9b327caa9af797529 upstream.

AF_PACKET TX_RING skbs keep a raw pointer to their ring frame. The skb
page references preserve page-backed ring blocks after pg_vec is freed,
but they do not preserve a vmalloc mapping.

tpacket_destruct_skb() currently drops the pending reference before
writing the timestamp and TP_STATUS_AVAILABLE to the frame. Move the
decrement after those stores. The smp_wmb() in __packet_set_status()
orders the frame stores before the decrement.

Also recheck pending TX frames under pg_vec_lock before non-closing
ring replacement, so a racing send cannot add a pending skb between
the initial check and the ring swap.

Ring allocation can produce a mixture of page-backed and vmalloc-backed
blocks. Allocate deferred-work storage during TX ring setup when the
first vmalloc-backed block is encountered, and keep its pointer in the
pg_vec allocation header. If allocation fails, return -ENOMEM from ring
setup. On socket close, a non-NULL pointer identifies a vmalloc-backed
vector without a scan. If TX skbs remain, defer the whole vector to
system_long_wq.

After pg_vec is detached, a late destructor can skip the pending
decrement. Use socket write-memory accounting as the deferred lifetime
gate instead: an skb remains charged through its final sock_wfree(),
after all ring-frame accesses. The delayed work retains a socket
reference and reschedules itself until no TX skbs remain.

Move pending_refcnt release to packet_sock_destruct() so late skb
destructors and deferred cleanup can safely use it after
packet_release(). Page-backed teardown remains synchronous, and no lock
is added to the TX completion hot path.

Fixes: b013840810c2 ("packet: use percpu mmap tx frame pending refcount")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/netdev/20260721015824.45829-1-kylebot@openai.com/
Suggested-by: Eric Dumazet <edumazet@google.com>
Suggested-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Kyle Zeng <kylebot@openai.com>
Link: https://patch.msgid.link/20260816235646.76500-1-kylebot@openai.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 net/packet/af_packet.c |   96 ++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 87 insertions(+), 9 deletions(-)

--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -88,6 +88,7 @@
 #include <linux/errqueue.h>
 #include <linux/net_tstamp.h>
 #include <linux/percpu.h>
+#include <linux/workqueue.h>
 #ifdef CONFIG_INET
 #include <net/inet_common.h>
 #endif
@@ -1341,6 +1342,8 @@ static void packet_sock_destruct(struct
 	WARN_ON(atomic_read(&sk->sk_rmem_alloc));
 	WARN_ON(refcount_read(&sk->sk_wmem_alloc));
 
+	packet_free_pending(pkt_sk(sk));
+
 	if (!sock_flag(sk, SOCK_DEAD)) {
 		pr_err("Attempt to release alive packet socket: %p\n", sk);
 		return;
@@ -2534,11 +2537,11 @@ static void tpacket_destruct_skb(struct
 		__u32 ts;
 
 		ph = skb_zcopy_get_nouarg(skb);
-		packet_dec_pending(&po->tx_ring);
 
 		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);
 	}
 
@@ -3207,7 +3210,6 @@ static int packet_release(struct socket
 	/* Purge queues */
 
 	skb_queue_purge(&sk->sk_receive_queue);
-	packet_free_pending(po);
 
 	sock_put(sk);
 	return 0;
@@ -4370,11 +4372,26 @@ static const struct vm_operations_struct
 	.close	=	packet_mm_close,
 };
 
+struct packet_pg_vec {
+	struct packet_pg_vec_free *deferred;
+	unsigned int order;
+	unsigned int len;
+	struct pgv pg_vec[] __counted_by(len);
+};
+
+struct packet_pg_vec_free {
+	struct delayed_work work;
+	struct sock *sk;
+	struct packet_pg_vec *vec;
+};
+
 static void free_pg_vec(struct pgv *pg_vec, unsigned int order,
 			unsigned int len)
 {
+	struct packet_pg_vec *vec;
 	int i;
 
+	vec = container_of_const(pg_vec, struct packet_pg_vec, pg_vec[0]);
 	for (i = 0; i < len; i++) {
 		if (likely(pg_vec[i].buffer)) {
 			if (is_vmalloc_addr(pg_vec[i].buffer))
@@ -4385,7 +4402,46 @@ static void free_pg_vec(struct pgv *pg_v
 			pg_vec[i].buffer = NULL;
 		}
 	}
-	kfree(pg_vec);
+	kfree(vec->deferred);
+	kfree(vec);
+}
+
+static void packet_free_pg_vec_work(struct work_struct *work)
+{
+	struct packet_pg_vec_free *deferred;
+	struct packet_pg_vec *vec;
+	struct sock *sk;
+
+	deferred = container_of_const(to_delayed_work(work),
+				      struct packet_pg_vec_free, work);
+	vec = deferred->vec;
+	sk = deferred->sk;
+	if (sk_wmem_alloc_get(sk)) {
+		queue_delayed_work(system_long_wq, &deferred->work, 1);
+		return;
+	}
+
+	free_pg_vec(vec->pg_vec, vec->order, vec->len);
+	sock_put(sk);
+}
+
+static void packet_free_tx_ring(struct sock *sk, struct pgv *pg_vec,
+				unsigned int order, unsigned int len)
+{
+	struct packet_pg_vec_free *deferred;
+	struct packet_pg_vec *vec;
+
+	vec = container_of_const(pg_vec, struct packet_pg_vec, pg_vec[0]);
+	deferred = vec->deferred;
+	if (!deferred || !sk_wmem_alloc_get(sk)) {
+		free_pg_vec(pg_vec, order, len);
+		return;
+	}
+
+	/* A detached ring's pending count can miss late skb destructors. */
+	deferred->sk = sk;
+	sock_hold(sk);
+	queue_delayed_work(system_long_wq, &deferred->work, 0);
 }
 
 static char *alloc_one_pg_vec_page(unsigned long order)
@@ -4413,20 +4469,35 @@ static char *alloc_one_pg_vec_page(unsig
 	return NULL;
 }
 
-static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order)
+static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order, bool tx_ring)
 {
 	unsigned int block_nr = req->tp_block_nr;
+	struct packet_pg_vec *vec;
 	struct pgv *pg_vec;
 	int i;
 
-	pg_vec = kzalloc_objs(struct pgv, block_nr, GFP_KERNEL | __GFP_NOWARN);
-	if (unlikely(!pg_vec))
-		goto out;
+	vec = kzalloc_flex(*vec, pg_vec, block_nr, GFP_KERNEL | __GFP_NOWARN);
+	if (unlikely(!vec))
+		return NULL;
+	vec->order = order;
+	vec->len = block_nr;
+	pg_vec = vec->pg_vec;
 
 	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:
@@ -4509,7 +4580,7 @@ static int packet_set_ring(struct sock *
 
 		err = -ENOMEM;
 		order = get_order(req->tp_block_size);
-		pg_vec = alloc_pg_vec(req, order);
+		pg_vec = alloc_pg_vec(req, order, tx_ring);
 		if (unlikely(!pg_vec))
 			goto out;
 		switch (po->tp_version) {
@@ -4561,6 +4632,9 @@ static int packet_set_ring(struct sock *
 	err = -EBUSY;
 	mutex_lock(&po->pg_vec_lock);
 	if (closing || atomic_long_read(&po->mapped) == 0) {
+		if (tx_ring && !closing && packet_read_pending(rb))
+			goto out_unlock;
+
 		err = 0;
 		spin_lock_bh(&rb_queue->lock);
 		swap(rb->pg_vec, pg_vec);
@@ -4582,6 +4656,7 @@ static int packet_set_ring(struct sock *
 			pr_err("packet_mmap: vma is busy: %ld\n",
 			       atomic_long_read(&po->mapped));
 	}
+out_unlock:
 	mutex_unlock(&po->pg_vec_lock);
 
 	spin_lock(&po->bind_lock);
@@ -4603,7 +4678,10 @@ static int packet_set_ring(struct sock *
 out_free_pg_vec:
 	if (pg_vec) {
 		bitmap_free(rx_owner_map);
-		free_pg_vec(pg_vec, order, req->tp_block_nr);
+		if (tx_ring && closing)
+			packet_free_tx_ring(sk, pg_vec, order, req->tp_block_nr);
+		else
+			free_pg_vec(pg_vec, order, req->tp_block_nr);
 	}
 out:
 	return err;



  parent reply	other threads:[~2026-08-31 13:41 UTC|newest]

Thread overview: 81+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-31 13:33 [PATCH 7.2 00/71] 7.2.3-rc1 review Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 01/71] RDMA/rxe: Fix responder UAF on IB_QP_MAX_DEST_RD_ATOMIC modify_qp Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 02/71] RDMA/rxe: Fix OOB in free_rd_atomic_resources() Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 03/71] nvme-tcp: fix usage of page_frag_cache Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 04/71] selftests/bpf: Fix test_maps sockmap failure Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 05/71] fpga: dfl: fme: add error handling Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 06/71] accessibility: speakup: unregister tty ldisc on later init failures Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 07/71] usb: xhci: Handle bogus TRB pointers in Missed Service Error events Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 08/71] usb: xhci: Handle USB3 port events when there is one roothub Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 09/71] usb: xhci: bail out of setup if the controller is inaccessible Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 10/71] xhci: dbgtty: Fix unregister on tty_register_driver() failure Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 11/71] xhci: dbgtty: Fix unregister on tty_alloc_driver() failure Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 12/71] fuse: fix race between interrupt and resend Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 13/71] fuse: fix missing barrier when checking io-uring readiness Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 14/71] fuse: publish io-uring queues with release semantics Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 15/71] fuse: wait for FR_FINISHED on abort_on_kill to prevent use-after-free Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 16/71] fuse: fix invalidate lock leak on setattr writeback failure Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 17/71] fuse: fix invalidate lock leak on open O_TRUNC DAX failure Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 18/71] usb: usbtest: disable dynamic ID support Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 19/71] usb: gadget: f_tcm: keep port count until LUN teardown completes Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 20/71] KVM: SEV: Allocate full pages for {DE,EN}CRYPT ops on SNP-enabled hosts Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 21/71] KVM: SEV: Drop FOLL_WRITE for encrypted region registration Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 22/71] KVM: SEV: Track the GPA of the guest-controlled VMSA used for SNP guests Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 23/71] KVM: SEV: Extract loading of guest-provided VMSA to a separate helper Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 24/71] KVM: SEV: Mark vCPU RUNNABLE after AP_CREATE, even if VMSA is unusable Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 25/71] KVM: SEV: Wire up kvm_x86_ops.gmem_xxx() if and only if CONFIG_KVM_AMD_SEV=y Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 26/71] tls: device: fix out-of-bounds write in tls_append_frag() Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 27/71] gtp: serialize PDP context updates Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 28/71] net/tcp: fix TCP-AO key deletion in VRFs Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 29/71] tcp: fix AO info use-after-free in tcp_ao_connect_init() Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 30/71] net/tcp-ao: fix use-after-free of current_key on reconnect to another peer Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 31/71] net: advertise TCP MSS from the configured MTU, not the learned PMTU Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 32/71] xfrm: espintcp: fix UAF during close Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 33/71] tcp: clamp route advmss to TCP_MIN_MSS Greg Kroah-Hartman
2026-08-31 13:33 ` [PATCH 7.2 34/71] xfrm: drop ESP-in-TCP packets with no ingress device Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 35/71] xfrm: avoid lock inversion in nat keepalive work Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 36/71] xfrm: ah6: validate routing header segments_left Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 37/71] xfrm: fix xfrm_state_construct() auth-trunc leak Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 38/71] xfrm: bound nat keepalive state collection Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 39/71] net: bridge: mcast: fix use-after-free of a master VLANs multicast context Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 40/71] vlan: fix skb_under_panic and races when toggling HW VLAN offload Greg Kroah-Hartman
2026-08-31 13:34 ` Greg Kroah-Hartman [this message]
2026-08-31 13:34 ` [PATCH 7.2 42/71] ipv6: seg6: clear IPv4 control block on IPIP decapsulation Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 43/71] batman-adv: reject unrepresentable multicast TVLV offsets Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 44/71] vxlan: keep the last remote linked during FDB flush Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 45/71] netfilter: nft_set_pipapo_avx2: add missing vzeroupper Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 46/71] netfilter: nf_tables: dont queue packet path object notifications Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 47/71] mm/swap: reject swapon() on filesystem-level encrypted files Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 48/71] kunit: irq: Continue increasing hrtimer interval for longer Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 49/71] crypto: virtio - bound the akcipher result length Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 50/71] crypto: qcom-rng - Enable clock in hwrng case Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 51/71] crypto: qcom-rng - Remove crypto_rng interface Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 52/71] crypto: qcom-rng - Allow zero as a random number Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 53/71] crypto: sun8i-ce - Remove crypto_rng interface Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 54/71] crypto: sun8i-ss " Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 55/71] crypto: atmel-tdes - use scatterlist length before DMA mapping Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 56/71] crypto: krb5 - use kfree_sensitive() for derived key buffers Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 57/71] crypto: qce - fix CCM AAD buffer underallocation Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 58/71] crypto: iaa - fall back to software for multi-entry scatterlists Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 59/71] crypto: mxs-dcp - fix source scatterlist length access Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 60/71] crypto: qce - Remove unsafe/deprecated algorithms Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 61/71] KVM: s390: vsie: zero stale crypto bits Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 62/71] usb: core: Add lock to usb_wakeup_notification() Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 63/71] usb: core: Strengthen error handling in hub_hub_status() Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 64/71] ALSA: usb-audio: Fix sample rates for PreSonus AudioBox USB Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 65/71] ALSA: usb-audio: fix OOB write in snd_usbmidi_novation_output() Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 66/71] ALSA: usb-audio: Complete cleanup after system-resume errors Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 67/71] USB: serial: option: fix slab OOB read in interrupt URB callback Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 68/71] USB: serial: spcp8x5: drop broken carrier detect support Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 69/71] USB: c67x00: fix use-after-free in c67x00_add_iso_urb() Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 70/71] wifi: mt76: mt7925: ensure tx headroom in usb_sdio_tx_prepare_skb Greg Kroah-Hartman
2026-08-31 13:34 ` [PATCH 7.2 71/71] usb: usbfs: fix use-after-free of usb_device in usbdev_release() Greg Kroah-Hartman
2026-08-31 16:18 ` [PATCH 7.2 00/71] 7.2.3-rc1 review Ronald Warsow
2026-08-31 19:12 ` Brett A C Sheffield
2026-09-01  2:30 ` Florian Fainelli
2026-09-01 12:39 ` Peter Schneider
2026-09-01 13:13 ` Takeshi Ogasawara
2026-09-01 16:43 ` Shuah Khan
2026-09-01 22:44 ` Miguel Ojeda
2026-09-01 22:53 ` Ron Economos
2026-09-02  7:53 ` Barry K. Nathan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260831133401.339016743@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=kylebot@openai.com \
    --cc=patches@lists.linux.dev \
    --cc=stable@vger.kernel.org \
    --cc=willemb@google.com \
    --cc=willemdebruijn.kernel@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.