From: Eric Dumazet <edumazet@kernel.org>
To: "David S . Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>,
netdev@vger.kernel.org, Eric Dumazet <edumazet@kernel.org>,
Stephan Lipp <Stephan@adalogics.com>
Subject: [PATCH net] net: shrink the payload-only part of skb dataref to one bit
Date: Tue, 20 Oct 2026 17:19:54 +0200 [thread overview]
Message-ID: <20261020151954.22953-1-edumazet@kernel.org> (raw)
skb_shinfo(skb)->dataref is split in two 16-bit halves: the lower
one counts all references, the upper one the payload-only (nohdr)
references.
__skb_clone() increments dataref without bound, and skb_cloned()
only checks the low 16 bits. With 65,537 references the low half
reads 1, the head looks private, and pskb_expand_head() (or
skb_unclone(), skb_cow(), ...) frees it while clones still point
to it.
An unprivileged user can reach this from a user and network namespace:
about 32,770 AF_PACKET sockets on lo bring dataref to 0x10001, then
any pskb_expand_head() on the receive path (here a pull of a large
IPv6 Hop-by-Hop header) frees the shared head:
BUG: KASAN: slab-use-after-free in _copy_to_iter+0x187/0x1330
Read of size 1590 at addr ff110001104a9002 by task dataref_wrap/87
skb_copy_datagram_iter+0x60/0x190
packet_recvmsg+0x1f5/0x12b0
__sys_recvfrom+0x18d/0x290
Freed by task 87:
kfree+0xf3/0x3b0
pskb_expand_head+0x344/0xeb0
__pskb_pull_tail+0xf9/0x1bf0
ipv6_parse_hopopts+0x377/0x4f0
ip6_rcv_core+0xc67/0x1620
The upper half never holds more than 1. It is only set by
__skb_header_release(), with atomic_set() on an skb owning its head
(TCP/SCTP output, and GRO which never sees cloned skbs).
__skb_clone() clears nohdr, and __copy_skb_header() does not copy it.
Move SKB_DATAREF_SHIFT to 30, so that the reference count gets 30 bits,
and dataref stays positive. Wrapping it would need 2^30 live clones of
a single skb, which socket buffer limits and memory make unreachable.
This issue was found by Anthropic using Claude, and validated by
Ada Logics.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: Stephan Lipp <Stephan@adalogics.com>
Signed-off-by: Eric Dumazet <edumazet@kernel.org>
---
include/linux/skbuff.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index a3ff380d43f01db0b040573c9dd7acc4e2e2cda8..58007e5db61e0228e773dc9ee688fcd1d056a345 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -633,9 +633,9 @@ struct skb_shared_info {
*
* Transport layers send out clones of payload skbs they hold for
* retransmissions. To allow lower layers of the stack to prepend their headers
- * we split &skb_shared_info.dataref into two halves.
- * The lower 16 bits count the overall number of references.
- * The higher 16 bits indicate how many of the references are payload-only.
+ * we split &skb_shared_info.dataref into two parts.
+ * The lower 30 bits count the overall number of references.
+ * Bit 30 indicates whether one of the references is payload-only.
* skb_header_cloned() checks if skb is allowed to add / write the headers.
*
* The creator of the skb (e.g. TCP) marks its skb as &sk_buff.nohdr
@@ -655,7 +655,7 @@ struct skb_shared_info {
* Having multiple payload-only skbs with different lengths of hdr_len is not
* possible. The payload-only skbs should never leave their owner.
*/
-#define SKB_DATAREF_SHIFT 16
+#define SKB_DATAREF_SHIFT 30
#define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1)
--
2.53.0
reply other threads:[~2026-10-20 15:20 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20261020151954.22953-1-edumazet@kernel.org \
--to=edumazet@kernel.org \
--cc=Stephan@adalogics.com \
--cc=davem@davemloft.net \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.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.