* [PATCH net v2] seg6: Fix unset mac header in SRv6 End.DT VRF decapsulation
@ 2026-10-17 12:01 Boyan Liu
2026-10-17 15:57 ` Willem de Bruijn
0 siblings, 1 reply; 2+ messages in thread
From: Boyan Liu @ 2026-10-17 12:01 UTC (permalink / raw)
To: Andrea Mayer, David Ahern, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Willem de Bruijn
Cc: netdev, linux-kernel, co+98d7de09cd94fec5
SRv6 End.DT4/End.DT6 VRF decapsulation unsets the mac header in
end_dt_vrf_rcv() so that the VRF device can rebuild it for packet
sniffers. The VRF rx handler only performs the rebuild when a
sniffer is actually attached to the VRF device (ptype_all
non-empty); otherwise the packet continues up the stack with
mac_header == 0xffff.
Every other receive path delivers packets with a valid mac header:
NIC drivers set it in eth_type_trans(), and tunnels without an L2
header (ipip, sit, gre, tun) reset it to the network header after
decapsulation. skb_mac_header() even warns on the unset state with
DEBUG_NET_WARN_ON_ONCE().
If the decapsulated packet is an unexpected UDP GSO packet,
udp_queue_rcv_skb() re-segments it after restoring skb->data to the
mac header with __skb_push(skb, -skb_mac_offset(skb)). With the mac
header unset, skb_mac_offset() returns a large positive value,
which the unsigned __skb_push() argument turns into a huge length:
skb->data moves far outside the buffer and skb->len is corrupted,
so segmentation reads out of bounds:
BUG: KASAN: slab-out-of-bounds in inet_gso_segment (net/ipv4/af_inet.c:1383)
Read of size 1 at addr ffff88800da7ffff by task exploit/149
Call Trace:
inet_gso_segment (net/ipv4/af_inet.c:1383)
skb_mac_gso_segment (net/core/gso.c:53)
__skb_gso_segment (net/core/gso.c:124)
udp_queue_rcv_skb (net/ipv4/udp.c:2476 net/ipv4/udp.c:2466)
udp_unicast_rcv_skb (net/ipv4/udp.c:2620)
ip_local_deliver (net/ipv4/ip_input.c:262)
seg6_local_input_core (net/ipv6/seg6_local.c:1640)
lwtunnel_input (net/core/lwtunnel.c:465)
ipv6_rcv (net/ipv6/ip6_input.c:351)
Restore a valid mac header, pointing at the network header, once
the VRF rx handler returns. The sniffer rebuild happens inside the
handler while the header is still unset, so tap behavior is
unchanged; when no rebuild happened, the packet now carries the
same mac header state as any packet received on an L3 device.
Fixes: 664d6f86868b ("seg6: add support for the SRv6 End.DT4 behavior")
Cc: stable@vger.kernel.org
Reported-by: co+98d7de09cd94fec5@bugs.sh
Signed-off-by: Boyan Liu <yymhvert@gmail.com>
---
v2:
- Move the fix from the UDP GSO path to seg6local.
- Restore the mac header after the VRF rx handler returns, preserving
the VRF sniffer behavior.
- Verify the original reproducer, datagram delivery, and VRF sniffer
output under QEMU.
v1: https://lore.kernel.org/netdev/20261010073015.7665-1-yymhvert@gmail.com/
net/ipv6/seg6_local.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
index 7b5212220185..5232c9e2b7d7 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -1113,6 +1113,14 @@ static struct sk_buff *end_dt_vrf_rcv(struct sk_buff *skb, u16 family,
/* the skb buffer was consumed by the handler */
return NULL;
+ /* the VRF device had its chance to rebuild the mac header for
+ * sniffers; restore a valid one pointing at the network header,
+ * like any L3 device without an L2 header, before the packet
+ * continues up the stack.
+ */
+ if (!skb_mac_header_was_set(skb))
+ skb_reset_mac_header(skb);
+
/* when a packet is received by a VRF or by one of its slaves, the
* master device reference is set into the skb.
*/
--
2.43.0
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH net v2] seg6: Fix unset mac header in SRv6 End.DT VRF decapsulation
2026-10-17 12:01 [PATCH net v2] seg6: Fix unset mac header in SRv6 End.DT VRF decapsulation Boyan Liu
@ 2026-10-17 15:57 ` Willem de Bruijn
0 siblings, 0 replies; 2+ messages in thread
From: Willem de Bruijn @ 2026-10-17 15:57 UTC (permalink / raw)
To: Boyan Liu, Andrea Mayer, David Ahern, David S . Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Willem de Bruijn
Cc: netdev, linux-kernel, co+98d7de09cd94fec5
Boyan Liu wrote:
> SRv6 End.DT4/End.DT6 VRF decapsulation unsets the mac header in
> end_dt_vrf_rcv() so that the VRF device can rebuild it for packet
> sniffers. The VRF rx handler only performs the rebuild when a
> sniffer is actually attached to the VRF device (ptype_all
> non-empty); otherwise the packet continues up the stack with
> mac_header == 0xffff.
>
> Every other receive path delivers packets with a valid mac header:
> NIC drivers set it in eth_type_trans(), and tunnels without an L2
> header (ipip, sit, gre, tun) reset it to the network header after
> decapsulation. skb_mac_header() even warns on the unset state with
> DEBUG_NET_WARN_ON_ONCE().
>
> If the decapsulated packet is an unexpected UDP GSO packet,
> udp_queue_rcv_skb() re-segments it after restoring skb->data to the
> mac header with __skb_push(skb, -skb_mac_offset(skb)). With the mac
> header unset, skb_mac_offset() returns a large positive value,
> which the unsigned __skb_push() argument turns into a huge length:
> skb->data moves far outside the buffer and skb->len is corrupted,
> so segmentation reads out of bounds:
>
> BUG: KASAN: slab-out-of-bounds in inet_gso_segment (net/ipv4/af_inet.c:1383)
> Read of size 1 at addr ffff88800da7ffff by task exploit/149
> Call Trace:
> inet_gso_segment (net/ipv4/af_inet.c:1383)
> skb_mac_gso_segment (net/core/gso.c:53)
> __skb_gso_segment (net/core/gso.c:124)
> udp_queue_rcv_skb (net/ipv4/udp.c:2476 net/ipv4/udp.c:2466)
> udp_unicast_rcv_skb (net/ipv4/udp.c:2620)
> ip_local_deliver (net/ipv4/ip_input.c:262)
> seg6_local_input_core (net/ipv6/seg6_local.c:1640)
> lwtunnel_input (net/core/lwtunnel.c:465)
> ipv6_rcv (net/ipv6/ip6_input.c:351)
>
> Restore a valid mac header, pointing at the network header, once
> the VRF rx handler returns. The sniffer rebuild happens inside the
> handler while the header is still unset, so tap behavior is
> unchanged; when no rebuild happened, the packet now carries the
> same mac header state as any packet received on an L3 device.
>
> Fixes: 664d6f86868b ("seg6: add support for the SRv6 End.DT4 behavior")
> Cc: stable@vger.kernel.org
> Reported-by: co+98d7de09cd94fec5@bugs.sh
> Signed-off-by: Boyan Liu <yymhvert@gmail.com>
> ---
> v2:
> - Move the fix from the UDP GSO path to seg6local.
> - Restore the mac header after the VRF rx handler returns, preserving
> the VRF sniffer behavior.
> - Verify the original reproducer, datagram delivery, and VRF sniffer
> output under QEMU.
> v1: https://lore.kernel.org/netdev/20261010073015.7665-1-yymhvert@gmail.com/
Thanks. As discussed in v1, this sounds the better approach to me too.
But it would be better to get the opinion of experts on VRF and SRv6.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-17 15:57 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-17 12:01 [PATCH net v2] seg6: Fix unset mac header in SRv6 End.DT VRF decapsulation Boyan Liu
2026-10-17 15:57 ` Willem de Bruijn
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®