If IPv6 is disabled on boot (ipv6.disable=1), but nft_fib_inet ends up dealing with a IPv6 packet, it causes a kernel panic in fib6_node_lookup_1(), crashing in bad_page_fault. The panic is caused by trying to deference a very low address (0x38 in ppc64le), due to ipv6.fib6_main_tbl = NULL. BUG: Kernel NULL pointer dereference at 0x00000038 Fix this behavior by dropping IPv6 packets if !ipv6_mod_enabled(). Signed-off-by: Leonardo Bras <leonardo@xxxxxxxxxxxxx> --- Changes from v2: - Replace veredict.code from NF_DROP to NFT_BREAK - Updated commit message (s/package/packet) Changes from v1: - Move drop logic from nft_fib_inet_eval() to nft_fib6_eval{,_type} so it can affect other usages of these functions. net/ipv6/netfilter/nft_fib_ipv6.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/ipv6/netfilter/nft_fib_ipv6.c b/net/ipv6/netfilter/nft_fib_ipv6.c index 7ece86afd079..8496e43b73bd 100644 --- a/net/ipv6/netfilter/nft_fib_ipv6.c +++ b/net/ipv6/netfilter/nft_fib_ipv6.c @@ -125,6 +125,11 @@ void nft_fib6_eval_type(const struct nft_expr *expr, struct nft_regs *regs, u32 *dest = ®s->data[priv->dreg]; struct ipv6hdr *iph, _iph; + if (!ipv6_mod_enabled()) { + regs->verdict.code = NFT_BREAK; + return; + } + iph = skb_header_pointer(pkt->skb, noff, sizeof(_iph), &_iph); if (!iph) { regs->verdict.code = NFT_BREAK; @@ -150,6 +155,11 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs, struct rt6_info *rt; int lookup_flags; + if (!ipv6_mod_enabled()) { + regs->verdict.code = NFT_BREAK; + return; + } + if (priv->flags & NFTA_FIB_F_IIF) oif = nft_in(pkt); else if (priv->flags & NFTA_FIB_F_OIF) -- 2.20.1