From: Ryan Prinz <rc4d5a@protonmail.com>
To: linux-wpan@vger.kernel.org, netdev@vger.kernel.org
Cc: Alexander Aring <alex.aring@gmail.com>,
Stefan Schmidt <stefan@datenfreihafen.org>,
Miquel Raynal <miquel.raynal@bootlin.com>,
"David S . Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@kernel.org>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>,
linux-kernel@vger.kernel.org, Ryan Prinz <rc4d5a@protonmail.com>
Subject: [PATCH net v2] ieee802154: 6lowpan: validate fragment offset against datagram size
Date: Thu, 12 Nov 2026 15:31:19 +0000 [thread overview]
Message-ID: <20261112153034.1015181-1-rc4d5a@protonmail.com> (raw)
In-Reply-To: <20261109090226.799973-1-rc4d5a@protonmail.com>
A 6LoWPAN fragment announces the total size of the datagram it belongs
to (d_size) and its own offset within that datagram. The reassembly
code never checks that the offset actually fits inside d_size, so a
fragment claiming to start past the end of the datagram is accepted
the same as a legitimate one.
lowpan_frag_queue() considers a datagram complete by counting bytes
received (fq->q.meat) against the declared size (fq->q.len), not by
verifying the bytes form a contiguous range. A fragment with an
out-of-range offset still has its length counted toward that total.
If an attacker's out-of-range fragment lands in a gap before the
legitimate fragment for that span arrives, inet_frag_queue_insert()
accepts the attacker's bytes into that span; when the legitimate
fragment for the same span then arrives, it collides with the
attacker's skb and is dropped as an overlap (IPFRAG_OVERLAP). The
datagram still completes, but with the attacker's bytes in the
reassembled buffer instead of the legitimate sender's.
IPv6's reassembly (net/ipv6/reassembly.c, ip6_frag_queue()) computes
end = offset + payload length for every fragment and checks end
against IPV6_MAXPLEN, which bounds offset by construction. 6LoWPAN's
d_offset and d_size are independent wire fields with no such coupling,
and no separate bounds check was added for it. RIOT-OS's 6LoWPAN
implementation (gnrc_sixlowpan_frag_rb_add) already rejects a fragment
once offset + size exceeds the reassembly buffer's datagram_size;
Linux's 6LoWPAN reassembly had no equivalent check.
Fixed by rejecting any fragment whose offset exceeds d_size, or whose
offset plus length would exceed d_size. A final fragment ending
exactly at d_size, including a zero-length one at offset == d_size, is
still accepted, matching the completion check right below it.
Fixes: 7240cdec60b1 ("6lowpan: handling 6lowpan fragmentation via inet_frag api")
Signed-off-by: Ryan Prinz <rc4d5a@protonmail.com>
---
v2:
- Reworded the impact description. 802.15.4 has no source
authentication without llsec, so this bug doesn't let an attacker
impersonate another sender; the real effect is that an attacker's
fragment can get spliced into the reassembled datagram in place of
a legitimate sender's bytes, with the legitimate fragment for that
span evicted as an overlap.
- Dropped the CVE-2019-8359/Contiki-NG comparison. That bug was an
out-of-bounds write into a fixed buffer; this one only corrupts the
reassembled payload's contents, since inet_frag_reasm_finish()
links fragment skbs by pointer rather than copying into a computed
offset. The two aren't the same severity class.
- Corrected the described accepted range: the check allows
offset + length == d_size, which it must for the final fragment
(including a zero-length one at offset == d_size), so the accepted
range has a closed upper bound, not the open "[0, d_size)" the v1
message stated.
No change to the fix itself; the diff in reassembly.c is unchanged
from v1.
Reproduced two ways: with a local kernel module calling
lowpan_frag_rcv() directly, and over mac802154_hwsim with three
independent processes standing in for sender, receiver and attacker.
An attacker in radio range who observes one fragment of an
in-progress transmission reads d_tag, d_size and the addressing in the
clear, then sends a single out-of-range fragment of its own before the
legitimate fragment for that span arrives. The receiver's reassembly
completes with the attacker's bytes in place of the legitimate
sender's for that span, and the legitimate fragment is dropped as an
overlap. Both reproducers were re-run against this fix to confirm the
out-of-range fragment is now rejected outright.
AI Disclosure: An AI assistant (Claude) was used to assist with the
analysis and testing. I have verified the vulnerability, the fix, and
the test results myself and take responsibility for this contribution,
per Documentation/process/coding-assistants.rst.
net/ieee802154/6lowpan/reassembly.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c
index ddb6a5817d09..905ba5f86844 100644
--- a/net/ieee802154/6lowpan/reassembly.c
+++ b/net/ieee802154/6lowpan/reassembly.c
@@ -103,6 +103,9 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq,
offset = lowpan_802154_cb(skb)->d_offset << 3;
end = lowpan_802154_cb(skb)->d_size;
+ if (offset > end || skb->len > end - offset)
+ goto err;
+
/* Is this the final fragment? */
if (offset + skb->len == end) {
/* If we already have some bits beyond end
--
2.51.2
prev parent reply other threads:[~2026-11-12 15:31 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-07 22:32 [PATCH] " Ryan Prinz
2026-11-08 13:05 ` [PATCH RESEND] " Ryan Prinz
2026-11-08 14:20 ` [PATCH net " Ryan Prinz
2026-11-09 9:03 ` Ryan Prinz
2026-11-12 9:05 ` netdev-bot+sashiko
2026-11-12 15:29 ` Ryan Prinz
2026-11-12 15:31 ` Ryan Prinz [this message]
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=20261112153034.1015181-1-rc4d5a@protonmail.com \
--to=rc4d5a@protonmail.com \
--cc=alex.aring@gmail.com \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wpan@vger.kernel.org \
--cc=miquel.raynal@bootlin.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=stefan@datenfreihafen.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®