Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nf_dup_netdev: add and use recursion counter

Now that the egress function can be called from egress hook, we need
to avoid recursive calls into the nf_tables traverser, else crash.

Fixes: f87b9464d152 ("netfilter: nft_fwd_netdev: Support egress hook")
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Florian Westphal and committed by
Pablo Neira Ayuso
fcd53c51 574a5b85

+15 -4
+15 -4
net/netfilter/nf_dup_netdev.c
··· 13 13 #include <net/netfilter/nf_tables_offload.h> 14 14 #include <net/netfilter/nf_dup_netdev.h> 15 15 16 + #define NF_RECURSION_LIMIT 2 17 + 18 + static DEFINE_PER_CPU(u8, nf_dup_skb_recursion); 19 + 16 20 static void nf_do_netdev_egress(struct sk_buff *skb, struct net_device *dev, 17 21 enum nf_dev_hooks hook) 18 22 { 23 + if (__this_cpu_read(nf_dup_skb_recursion) > NF_RECURSION_LIMIT) 24 + goto err; 25 + 19 26 if (hook == NF_NETDEV_INGRESS && skb_mac_header_was_set(skb)) { 20 - if (skb_cow_head(skb, skb->mac_len)) { 21 - kfree_skb(skb); 22 - return; 23 - } 27 + if (skb_cow_head(skb, skb->mac_len)) 28 + goto err; 29 + 24 30 skb_push(skb, skb->mac_len); 25 31 } 26 32 27 33 skb->dev = dev; 28 34 skb_clear_tstamp(skb); 35 + __this_cpu_inc(nf_dup_skb_recursion); 29 36 dev_queue_xmit(skb); 37 + __this_cpu_dec(nf_dup_skb_recursion); 38 + return; 39 + err: 40 + kfree_skb(skb); 30 41 } 31 42 32 43 void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif)