nft_fib_can_skip() dereferences the input device (indev->ifindex, and in->flags via nft_fib_is_loopback()) without a NULL check, assuming the hook switch only admits PRE_ROUTING/INGRESS/LOCAL_IN. But NF_NETDEV_EGRESS == NF_INET_LOCAL_IN == 1, so a netdev-family base chain on the egress hook passes both the switch and nft_fib_validate() (which also keys only on the hook number). Egress packets have no input device, so nft_fib_can_skip() dereferences NULL. KASAN: null-ptr-deref in range [0x00000000000000b0-0x00000000000000b7] RIP: 0010:nft_fib4_eval (net/netfilter/nft_fib.h:19) nft_do_chain (net/netfilter/nf_tables_core.c:285) nft_do_chain_netdev (net/netfilter/nft_chain_filter.c:307) nf_hook_slow (net/netfilter/core.c:619) __dev_queue_xmit (net/core/dev.c:4799) ... Kernel panic - not syncing: Fatal exception in interrupt The eval path touched the device only via l3mdev_master_ifindex_rcu(), which tolerates NULL, until commit eaaff9b6702e ("netfilter: fib: avoid lookup if socket is available") added the sk/indev dereference. Restore the old behaviour by returning early when indev is NULL, so the packet takes the regular FIB lookup. Receive-side hooks always have an input device and are unaffected. Fixes: eaaff9b6702e ("netfilter: fib: avoid lookup if socket is available") Reported-by: AutonomousCodeSecurity@microsoft.com Signed-off-by: Xiang Mei (Microsoft) --- include/net/netfilter/nft_fib.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/net/netfilter/nft_fib.h b/include/net/netfilter/nft_fib.h index e0422456f27b..d53e5a5214fe 100644 --- a/include/net/netfilter/nft_fib.h +++ b/include/net/netfilter/nft_fib.h @@ -33,6 +33,9 @@ static inline bool nft_fib_can_skip(const struct nft_pktinfo *pkt) return false; } + if (!indev) + return false; + sk = pkt->skb->sk; if (sk && sk_fullsock(sk)) return sk->sk_rx_dst_ifindex == indev->ifindex; -- 2.43.0