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 <leona...@linux.ibm.com>
---
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 = &regs->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

Reply via email to