mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH net] ipv4: reject impossible oversized fragments at queue time
@ 2026-07-17  7:41 Yuxiang Yang
  2026-07-17 19:33 ` Eric Dumazet
  0 siblings, 1 reply; 2+ messages in thread
From: Yuxiang Yang @ 2026-07-17  7:41 UTC (permalink / raw)
  To: netdev
  Cc: dsahern, idosch, davem, edumazet, kuba, pabeni, horms,
	linux-kernel, Yuxiang Yang, stable, Yizhou Zhao, Ao Wang,
	Xuewei Feng, Qi Li, Ke Xu, yyxroy22

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 <yangyx22@mails.tsinghua.edu.cn>
---
 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


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

* Re: [PATCH net] ipv4: reject impossible oversized fragments at queue time
  2026-07-17  7:41 [PATCH net] ipv4: reject impossible oversized fragments at queue time Yuxiang Yang
@ 2026-07-17 19:33 ` Eric Dumazet
  0 siblings, 0 replies; 2+ messages in thread
From: Eric Dumazet @ 2026-07-17 19:33 UTC (permalink / raw)
  To: Yuxiang Yang
  Cc: netdev, dsahern, idosch, davem, kuba, pabeni, horms,
	linux-kernel, stable, Yizhou Zhao, Ao Wang, Xuewei Feng, Qi Li,
	Ke Xu, yyxroy22

On Fri, Jul 17, 2026 at 9:41 AM Yuxiang Yang
<yangyx22@mails.tsinghua.edu.cn> wrote:
>
> 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.

I have a hard time understanding the issue.

This is an invalid packet, why should we add more bloat to
the kernel just to 'optimize' this case?

You understand that IP frags are unreliable no matter how hard we try
to 'fix' them, right ?



>
> 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 <yangyx22@mails.tsinghua.edu.cn>
> ---
>  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
>

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

end of thread, other threads:[~2026-07-17 19:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-17  7:41 [PATCH net] ipv4: reject impossible oversized fragments at queue time Yuxiang Yang
2026-07-17 19:33 ` Eric Dumazet

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