Thread (2 messages) 2 messages, 2 authors, 2d ago
WARM2d

[PATCH net] ipv4: reject impossible oversized fragments at queue time

From: Yuxiang Yang <hidden>
Date: 2026-07-17 07:41:41
Also in: lkml, stable
Subsystem: networking [general], networking [ipv4/ipv6], the rest · Maintainers: "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, David Ahern, Ido Schimmel, Linus Torvalds

ip_frag_queue() computes each incoming fragment's end offset and may
store it in qp->q.len without checking that the fragment can fit within
the 65535 byte IPv4 datagram limit, even with the minimum IPv4 header.
The only 65535 byte check lives later in ip_frag_reasm(), after the
fragment has already been accepted into the reassembly queue and has
updated its state.

A fragment whose end offset exceeds 65535 minus the minimum 20-byte IPv4
header cannot be part of any valid IPv4 datagram. Letting it update
qp->q.len leaves the shared reassembly queue with an impossible expected
length. A later legitimate two-fragment datagram sharing that key can no
longer complete reassembly and is not delivered.

This was verified at runtime on Linux 6.12.93-0-virt. A same-key
oversized-fragment injection (offset 65528, payload 8, end 65536) drove
legitimate two-fragment UDP delivery from 8/8 to 0/8, while a cross-ID
control stayed at 8/8.

With this change applied to net main, the same-key test delivered 8/8.
A valid 65535-byte datagram with a 20-byte header was also delivered with
both in-order and reverse-order fragments; its 65507-byte UDP payload
was intact in both cases.

Add a per-fragment bound check in ip_frag_queue() right after computing
end and before any qp->q.len update or skb insertion. IPv4 always needs
at least a struct iphdr, so an end offset greater than IP_MAX_MTU minus
sizeof(struct iphdr) cannot fit in any valid IPv4 datagram. Use that
minimum-header bound rather than the current fragment's IHL because
fragments may arrive out of order and the first fragment may carry
non-copied options that later fragments lack. The existing check in
ip_frag_reasm() continues to validate the final length against the
actual header length of the first fragment.

Drop only the invalid skb so an existing queue for the same key remains
intact.

The issue was found by Yuxiang Yang, Yizhou Zhao, Ao Wang, Xuewei Feng,
Qi Li, and Ke Xu, with assistance from GLM-5.2 by Z.ai.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Yuxiang Yang <redacted>
---
 net/ipv4/ip_fragment.c | 2 ++
 1 file changed, 2 insertions(+)
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index c790d2f49..32e5240a5 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -291,6 +291,8 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb, int *refs)
 	/* Determine the position of this fragment. */
 	end = offset + skb->len - skb_network_offset(skb) - ihl;
 	err = -EINVAL;
+	if (end > IP_MAX_MTU - sizeof(struct iphdr))
+		goto err;
 
 	/* Is this the final fragment? */
 	if ((flags & IP_MF) == 0) {
-- 
2.34.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help