mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH net v2] ipv6: seg6: clear IPv4 control block in End.DT4
@ 2026-08-04  9:46 David Lee
  2026-08-04 14:50 ` Nicolas Dichtel
  0 siblings, 1 reply; 4+ messages in thread
From: David Lee @ 2026-08-04  9:46 UTC (permalink / raw)
  To: andrea.mayer, davem, edumazet, kuba, pabeni
  Cc: Kyle Zeng, Dominik 'Disconnect3d' Czarnota,
	Nicolas Dichtel, horms, netdev, linux-kernel, David Lee

From: Kyle Zeng <kylebot@openai.com>

The End.DT4 input path decapsulates an IPv4 packet and sends it
directly to ip_route_input() and dst_input(). It therefore bypasses
ip_rcv_core(), which normally clears IPCB. The skb still contains
IP6CB data from the outer packet, and IPv6 extension-header offsets
overlap the IPv4 option fields. This can make __ip_options_echo()
copy beyond the allocation for saved options.

Clear IPCB after validating the inner IPv4 header and preserve the
ingress interface as ip_rcv_core() does. This prevents outer IPv6
metadata from being interpreted as inner IPv4 options.

Fixes: 664d6f86868b ("seg6: add support for the SRv6 End.DT4 behavior")
Assisted-by: Codex:gpt-5.6-sol Codex:gpt-5.5-cyber
Signed-off-by: Kyle Zeng <kylebot@openai.com>
Co-developed-by: David Lee <david.lee@trailofbits.com>
Signed-off-by: David Lee <david.lee@trailofbits.com>
---
Changes in v2:
- Restore Kyle Zeng as the patch author and correct the sign-off chain.

v1: https://lore.kernel.org/all/20260731140832.567669-1-david.lee@trailofbits.com/

Trail of Bits has a reproducer for this bug that triggers a KASAN
slab-out-of-bounds write in __ip_options_echo() and can share if needed.

 net/ipv6/seg6_local.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
index 2b41e4c0d..d03b377f5 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -1186,6 +1186,9 @@ static int input_action_end_dt4(struct sk_buff *skb,
 	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
 		goto drop;
 
+	memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+	IPCB(skb)->iif = skb->skb_iif;
+
 	skb = end_dt_vrf_core(skb, slwt, AF_INET);
 	if (!skb)
 		/* packet has been processed and consumed by the VRF */
-- 
2.53.0

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

* Re: [PATCH net v2] ipv6: seg6: clear IPv4 control block in End.DT4
  2026-08-04  9:46 [PATCH net v2] ipv6: seg6: clear IPv4 control block in End.DT4 David Lee
@ 2026-08-04 14:50 ` Nicolas Dichtel
       [not found]   ` <CAC_etQFJTsCN5zr_gxO_SEDjbJU4-yph0ezbvQ6zZ9ZVaLie0w@mail.gmail.com>
  0 siblings, 1 reply; 4+ messages in thread
From: Nicolas Dichtel @ 2026-08-04 14:50 UTC (permalink / raw)
  To: David Lee, andrea.mayer, davem, edumazet, kuba, pabeni
  Cc: Kyle Zeng, Dominik 'Disconnect3d' Czarnota, horms,
	netdev, linux-kernel

Le 04/08/2026 à 11:46, David Lee a écrit :
> From: Kyle Zeng <kylebot@openai.com>
> 
> The End.DT4 input path decapsulates an IPv4 packet and sends it
> directly to ip_route_input() and dst_input(). It therefore bypasses
> ip_rcv_core(), which normally clears IPCB. The skb still contains
> IP6CB data from the outer packet, and IPv6 extension-header offsets
> overlap the IPv4 option fields. This can make __ip_options_echo()
> copy beyond the allocation for saved options.
> 
> Clear IPCB after validating the inner IPv4 header and preserve the
> ingress interface as ip_rcv_core() does. This prevents outer IPv6
> metadata from being interpreted as inner IPv4 options.
> 
> Fixes: 664d6f86868b ("seg6: add support for the SRv6 End.DT4 behavior")
> Assisted-by: Codex:gpt-5.6-sol Codex:gpt-5.5-cyber
> Signed-off-by: Kyle Zeng <kylebot@openai.com>
> Co-developed-by: David Lee <david.lee@trailofbits.com>
> Signed-off-by: David Lee <david.lee@trailofbits.com>
> ---
> Changes in v2:
> - Restore Kyle Zeng as the patch author and correct the sign-off chain.

You didn't answer my previous question:

> End.DX4 also calls ip_route_input(). I guess the same problem exists. Am I
> wrong?

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

* Re: [PATCH net v2] ipv6: seg6: clear IPv4 control block in End.DT4
       [not found]   ` <CAC_etQFJTsCN5zr_gxO_SEDjbJU4-yph0ezbvQ6zZ9ZVaLie0w@mail.gmail.com>
@ 2026-08-05 11:58     ` Nicolas Dichtel
  2026-08-09 20:19       ` Andrea Mayer
  0 siblings, 1 reply; 4+ messages in thread
From: Nicolas Dichtel @ 2026-08-05 11:58 UTC (permalink / raw)
  To: David Lee
  Cc: andrea.mayer, davem, edumazet, kuba, pabeni, Kyle Zeng,
	Dominik 'Disconnect3d' Czarnota, horms, netdev,
	linux-kernel

Le 05/08/2026 à 12:17, David Lee a écrit :
> Hi Nicoals,
Hi,

please avoid top-posting ;-)
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst#n336
> 
> You were right. I tested End.DX4 separately on the 62cc90241548 (v7.2-rc5)
> kernel and it produced:
> 
> BUG: KASAN: slab-out-of-bounds in __ip_options_echo()
> Write of size 255
> 
> The stack contains both input_action_end_dx4_finish() and
> input_action_end_dx4(). A matched bounded control traversed End.DX4,
> reached SYN_RECV, and produced no kernel diagnostic.
> 
>  Therefore, End.DX4 has the same stale IP6CB-to-IPCB issue. The current
>  patch only clears IPCB in End.DT4 and is incomplete.
> 
> Do you prefer v3 to be sent out to cover this case too?
Yes, it would be nice to fix both in the same time.

Regards,
Nicolas

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

* Re: [PATCH net v2] ipv6: seg6: clear IPv4 control block in End.DT4
  2026-08-05 11:58     ` Nicolas Dichtel
@ 2026-08-09 20:19       ` Andrea Mayer
  0 siblings, 0 replies; 4+ messages in thread
From: Andrea Mayer @ 2026-08-09 20:19 UTC (permalink / raw)
  To: David Lee, Nicolas Dichtel
  Cc: davem, edumazet, kuba, pabeni, David Ahern, Kyle Zeng,
	Dominik 'Disconnect3d' Czarnota, horms, netdev,
	linux-kernel, stefano.salsano, Andrea Mayer

On Wed, 5 Aug 2026 13:58:21 +0200
Nicolas Dichtel <nicolas.dichtel@6wind.com> wrote:

Thanks Kyle and David for the patch, and Nicolas for catching the End.DX4
gap. Before v3, a few comments on the commit message and on the code.

> Le 05/08/2026 à 12:17, David Lee a écrit :
> > BUG: KASAN: slab-out-of-bounds in __ip_options_echo()
> > Write of size 255

Putting the KASAN trace in the commit message would show the impact
concretely and tell a reviewer how the problem is reached.
Is the reproducer available somewhere? I'm wondering if it could easily be
turned into a test, both to check that the fix works as expected and to
help discover other related issues.

> >  Therefore, End.DX4 has the same stale IP6CB-to-IPCB issue. The current
> >  patch only clears IPCB in End.DT4 and is incomplete.
> >
> > Do you prefer v3 to be sent out to cover this case too?
> Yes, it would be nice to fix both in the same time.

End.DX4 and End.DT4 both reach the inner IPv4 packet through
decap_and_validate(skb, IPPROTO_IPIP). End.DT46 dispatches to End.DT4, so
it is covered either way. Handling IPPROTO_IPIP inside decap_and_validate()
covers End.DX4 too, so v3 would need a single memset there instead of one
in input_action_end_dt4() and another in input_action_end_dx4(). Something
like:

  if (proto == IPPROTO_IPIP) {
      int iif = IP6CB(skb)->iif;

      memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
      IPCB(skb)->iif = iif;
  }

On the interface index: I would take it from IP6CB->iif before the memset,
rather than from skb->skb_iif. IP6CB->iif is what ip6_rcv_core() recorded
for the outer packet: the interface that packet is considered to have
arrived on. That value does not come from the headers that have just been
removed, so removing them does not make it stale. skb->skb_iif is the
right source in ip_rcv_core(), which runs before l3mdev, but End.DX4 and
End.DT4 run after l3mdev.

When the packet is received on an interface enslaved to a VRF,
ip6_rcv_core() puts that interface in IP6CB->iif and l3mdev then replaces
skb->skb_iif with the L3 master. In decap_and_validate() IP6CB->iif still
holds the receiving interface and skb->skb_iif holds the VRF.

I ran some tests on net/main and on two variants of the fix that differ
only in what they write into IPCB->iif. The packet arrives on ifindex 8,
enslaved to the VRF with ifindex 9, and the receiver is a UDP socket bound
to the VRF reading IP_PKTINFO:

                  no fix   iif from skb->skb_iif   iif saved
    End.DX4            8                       9           8
    End.DT4            8                       9           8

The no fix column is net/main unchanged: seg6_local.c does not write
IPCB->iif at all, so IP_PKTINFO reports what ip6_rcv_core() wrote in
IP6CB->iif, read through IPCB because iif is at the same offset in
inet_skb_parm and inet6_skb_parm.

So the two are not interchangeable: taking the index from skb->skb_iif
makes IP_PKTINFO report the VRF instead of the receiving interface, taking
it from IP6CB->iif before the memset does not.
IP_PKTINFO is not the only reader of IPCB->iif. With skb->skb_iif that
field holds the VRF (ifindex 9), and after End.DT4 a socket listening on
the receiving interface (ifindex 8) does not see the traffic.

It is also worth reconsidering the Fixes tag: decap_and_validate() has
never cleared the control block, and its first IPPROTO_IPIP caller is
End.DX4 in 891ef8dd2a8d ("ipv6: sr: implement additional seg6local
actions"), which predates 664d6f86868b ("seg6: add support for the SRv6
End.DT4 behavior").


Two side notes, both of which the Sashiko automated review also raises. The
same stale control block is left on the IPv6 side: with an outer Hop-by-Hop
header IP6CB->nhoff points into the inner payload and I see those packets
dropped as an unknown protocol. And input_action_end_dx4() and
end_dt_vrf_core() set the transport header at sizeof(struct iphdr), so it
points inside the options when the inner IPv4 packet carries them. I have a
reproducer for each and will send the two patches separately.

Thanks,

Ciao,
Andrea

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

end of thread, other threads:[~2026-08-09 20:25 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-04  9:46 [PATCH net v2] ipv6: seg6: clear IPv4 control block in End.DT4 David Lee
2026-08-04 14:50 ` Nicolas Dichtel
     [not found]   ` <CAC_etQFJTsCN5zr_gxO_SEDjbJU4-yph0ezbvQ6zZ9ZVaLie0w@mail.gmail.com>
2026-08-05 11:58     ` Nicolas Dichtel
2026-08-09 20:19       ` Andrea Mayer

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®