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: fe94cc290f ("bpf: Add IPv6 Segment Routing helpers")
Fixes: ad84b1eefe ("bpf: remove ipv6_bpf_stub completely and use direct function calls")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-25-alexei.starovoitov@gmail.com
This commit is contained in:
Alexei Starovoitov 2026-11-01 19:05:32 +00:00
parent d9618a6196
commit 95f1d5e4ab
No known key found for this signature in database
2 changed files with 5 additions and 1 deletions

View File

@ -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;

View File

@ -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 {