Netdev List
 help / color / mirror / Atom feed
* [PATCH net v2 0/1] ipv4: fix a non-progressing fragmentation loop from undersized effective MTUs
@ 2026-08-13 17:35 Ren Wei
  2026-08-13 17:35 ` [PATCH net v2 1/1] ipv4: reject undersized MTUs in ip_do_fragment() Ren Wei
  0 siblings, 1 reply; 2+ messages in thread
From: Ren Wei @ 2026-08-13 17:35 UTC (permalink / raw)
  To: netdev
  Cc: dsahern, idosch, davem, edumazet, kuba, pabeni, horms, vega,
	edragain, weir

From: Yong Wang <edragain@163.com>

Hi Linux kernel maintainers,

This series fixes a non-progressing IPv4 fragmentation loop in
net/ipv4/ip_output.c. The bug is reachable by a non-root user with
CAP_NET_ADMIN in a user-created user and network namespace.

---- details below ----

Bug details:

ip_do_fragment() subtracts the IPv4 header length from the effective
MTU and passes the resulting payload MTU to ip_frag_next().

If the effective MTU is smaller than hlen + 8, ip_frag_next() rounds
the fragment payload length down to zero. The fragmentation state then
never makes forward progress: state->left, state->ptr and state->offset
stay unchanged while ip_do_fragment() keeps allocating and transmitting
header-only fragments until the softlockup detector fires.

This is reproducible with a route installed using "mtu lock 20", but it
is also reproducible without route MTU lock, for example by forwarding a
packet to a device whose MTU is 20.

Because the failure happens in the fragmentation path itself, this
series fixes it in ip_do_fragment() by rejecting mtu < hlen + 8 with
-EMSGSIZE, matching the existing IPv6 fragmentation check.

The bug is reachable through more than one userspace-controlled path. A
user with CAP_NET_ADMIN in a user-created network namespace can trigger
it either by installing an undersized locked route MTU or by forwarding
through an egress device whose MTU is too small.

Tested in a 2 vCPU, 2 GB RAM x86 QEMU guest:

- the old kernel reproduces the softlockup both with "mtu lock 20" and
  with a dummy egress device whose MTU is 20
- the new kernel returns packet loss in the no-route-mtu-lock reproducer
  and the guest remains alive

Reproducer:

Run inside the guest as root:

    bash poc.sh

The PoC sets up forwarding through an egress dummy device whose MTU is
20, without installing any route MTU lock, and injects one forwarded
non-DF ping from a child netns.

We run the PoC in a 2 vCPU, 2 GB RAM x86 QEMU environment.

v2:
  - move the fix from ip_metrics_convert() to ip_do_fragment()
  - update the commit message and cover letter per reviewer and Sashiko
    feedback
  - switch the cover-letter reproducer to the no-route-mtu-lock
    dummy-device case

v1: https://lore.kernel.org/netdev/cover.1786094799.git.edragain@163.com/

------BEGIN poc.sh------

#!/bin/bash

sysctl -w net.ipv4.ip_forward=1

ip link add name dummy1 up mtu 20 type dummy
ip address add 192.0.2.1/24 dev dummy1

ip link add veth0 type veth peer name veth1
ip addr add 198.51.100.1/24 dev veth0
ip link set veth0 up

ip netns add ns1
ip link set veth1 netns ns1
ip -n ns1 address add 198.51.100.2/24 dev veth1
ip -n ns1 link set veth1 up
ip -n ns1 route add default via 198.51.100.1
ip netns exec ns1 ping -M dont -s 1000 -c 1 192.0.2.2

------END poc.sh--------

Best regards,
Yong Wang

Yong Wang (1):
  ipv4: reject undersized MTUs in ip_do_fragment()

 net/ipv4/ip_output.c | 4 ++++
 1 file changed, 4 insertions(+)

-- 
2.53.0


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

* [PATCH net v2 1/1] ipv4: reject undersized MTUs in ip_do_fragment()
  2026-08-13 17:35 [PATCH net v2 0/1] ipv4: fix a non-progressing fragmentation loop from undersized effective MTUs Ren Wei
@ 2026-08-13 17:35 ` Ren Wei
  0 siblings, 0 replies; 2+ messages in thread
From: Ren Wei @ 2026-08-13 17:35 UTC (permalink / raw)
  To: netdev
  Cc: dsahern, idosch, davem, edumazet, kuba, pabeni, horms, vega,
	edragain, weir

From: Yong Wang <edragain@163.com>

ip_do_fragment() subtracts the IPv4 header length from the effective
MTU and passes the resulting payload MTU to ip_frag_next().

If the effective MTU is smaller than hlen + 8, ip_frag_next() rounds
the fragment payload length down to zero. The fragmentation state then
never makes forward progress: state->left, state->ptr and state->offset
stay unchanged while ip_do_fragment() keeps allocating and transmitting
header-only fragments until the softlockup detector fires.

This is reproducible with a route installed using "mtu lock 20", but it
is also reproducible without route MTU lock, for example by forwarding a
packet to a device whose MTU is 20.

Fix it in ip_do_fragment() by rejecting mtu < hlen + 8 with -EMSGSIZE,
matching the existing IPv6 fragmentation check.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reported-by: Vega <vega@nebusec.ai>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Yong Wang <edragain@163.com>
Signed-off-by: Ren Wei <weir@nebusec.ai>
---
 net/ipv4/ip_output.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index e6dd1e5b8c32..74e095b6b7ca 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -790,6 +790,10 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
 	 */
 
 	hlen = iph->ihl * 4;
+	if (mtu < hlen + 8) {
+		err = -EMSGSIZE;
+		goto fail;
+	}
 	mtu = mtu - hlen;	/* Size of data space */
 	IPCB(skb)->flags |= IPSKB_FRAG_COMPLETE;
 	ll_rs = LL_RESERVED_SPACE(rt->dst.dev);
-- 
2.53.0

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

end of thread, other threads:[~2026-08-13 17:35 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-13 17:35 [PATCH net v2 0/1] ipv4: fix a non-progressing fragmentation loop from undersized effective MTUs Ren Wei
2026-08-13 17:35 ` [PATCH net v2 1/1] ipv4: reject undersized MTUs in ip_do_fragment() Ren Wei

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