From 95f1d5e4abb79fe85a54f7a46b41f297ce533c31 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Sun, 1 Nov 2026 19:05:32 +0000 Subject: [PATCH] bpf: Don't let lwt_in progs call into IPv6 when it is disabled With ipv6.disable=1, inet6_init() returns before it registers any pernet subsystem. Thus net->ipv6.devconf_all and net->ipv6.seg6_data stay NULL. IS_ENABLED(CONFIG_IPV6) only says that the code is built in. bpf_lwt_input_reroute() and bpf_push_seg6_encap() call into IPv6, but do not test ipv6_mod_enabled(). An lwt_in prog also runs with ipv6.disable=1, and skb->protocol == htons(ETH_P_IPV6) does not prove that IPv6 is enabled. Thus the kernel dereferences NULL and crashes. Return -EAFNOSUPPORT before these calls if ipv6_mod_enabled() is false. BPF_LWT_REROUTE then drops an IPv6 skb. With IPv6 enabled nothing changes. The first Fixes tag is for bpf_push_seg6_encap(), which never had this test. The second tag is for bpf_lwt_input_reroute(). Until that commit it used ipv6_stub, which returned -EAFNOSUPPORT with ipv6.disable=1. Fixes: fe94cc290f53 ("bpf: Add IPv6 Segment Routing helpers") Fixes: ad84b1eefe28 ("bpf: remove ipv6_bpf_stub completely and use direct function calls") Signed-off-by: Alexei Starovoitov Link: https://patch.msgid.link/20261101190535.1454146-25-alexei.starovoitov@gmail.com --- net/core/filter.c | 4 ++++ net/core/lwt_bpf.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/net/core/filter.c b/net/core/filter.c index 482f8132d9ca..08168ea381c2 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -6924,6 +6924,10 @@ static int bpf_push_seg6_encap(struct sk_buff *skb, u32 type, void *hdr, u32 len int err; struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)hdr; + /* With ipv6.disable=1 the netns has no seg6 data and no IPv6 tables. */ + if (!ipv6_mod_enabled()) + return -EAFNOSUPPORT; + if (!seg6_validate_srh(srh, len, false)) return -EINVAL; diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c index 60f4eda7dae9..774fad4e9fbf 100644 --- a/net/core/lwt_bpf.c +++ b/net/core/lwt_bpf.c @@ -128,7 +128,7 @@ static int bpf_lwt_input_reroute(struct sk_buff *skb) dev_put(dev); } else if (skb->protocol == htons(ETH_P_IPV6)) { skb_dst_drop(skb); - if (IS_ENABLED(CONFIG_IPV6)) { + if (ipv6_mod_enabled()) { ip6_route_input(skb); err = skb_dst(skb)->error; } else {