From 701ffd202b9e32942c8cfc065c9fe76ceaccc302 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Sun, 1 Nov 2026 19:05:29 +0000 Subject: [PATCH] bpf: Don't leave a stale MAC header in bpf_lwt_push_ip_encap() With BPF_LWT_ENCAP_IP, bpf_lwt_push_encap() pushes a new IP header. The new header overwrites the MAC header of a received skb. But skb->mac_header continues to point to the same bytes. Code that reads the MAC header after the push, for example netfilter, gets bytes of the new header. before the push | MAC header | old IP | payload ^ mac_header ^ network_header today | new header | old IP | payload network_header ^ ^ mac_header this patch, lwt_in | MAC header | new header | old IP | payload ^ mac_header ^ network_header this patch, lwt_xmit | new header | old IP | payload network_header ^ mac_header is not set For lwt_in, move the MAC header in front of the new header before the memcpy(), as __seg6_do_srh_encap() does. skb_cow_head() already reserves len + skb->mac_len bytes. For lwt_xmit, the output path makes a new MAC header. Thus mark skb->mac_header as not set. This is the state of a locally generated skb. Fixes: 52f278774e79 ("bpf: implement BPF_LWT_ENCAP_IP mode in bpf_lwt_push_encap") Signed-off-by: Alexei Starovoitov Link: https://patch.msgid.link/20261101190535.1454146-22-alexei.starovoitov@gmail.com --- net/core/lwt_bpf.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c index da49364ec63d..b9270a08cc6d 100644 --- a/net/core/lwt_bpf.c +++ b/net/core/lwt_bpf.c @@ -649,6 +649,14 @@ int bpf_lwt_push_ip_encap(struct sk_buff *skb, void *hdr, u32 len, bool ingress) if (ingress) skb_postpush_rcsum(skb, iph, len); skb_reset_network_header(skb); + /* + * The new header goes over the MAC header. On ingress move it first. + * On egress the packet gets a new one, so forget the old one. + */ + if (ingress) + skb_mac_header_rebuild(skb); + else + skb_unset_mac_header(skb); if (is_udp_tunnel) { size_t iph_sz = ipv4 ? iph->ihl * 4 : sizeof(struct ipv6hdr);