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: f87b9464d1 ("netfilter: nft_fwd_netdev: Support egress hook")
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Florian Westphal 2022-06-20 16:17:31 +02:00 committed by Pablo Neira Ayuso
parent 574a5b85dc
commit fcd53c51d0
1 changed files with 15 additions and 4 deletions

View File

@ -13,20 +13,31 @@
#include <net/netfilter/nf_tables_offload.h> #include <net/netfilter/nf_tables_offload.h>
#include <net/netfilter/nf_dup_netdev.h> #include <net/netfilter/nf_dup_netdev.h>
#define NF_RECURSION_LIMIT 2
static DEFINE_PER_CPU(u8, nf_dup_skb_recursion);
static void nf_do_netdev_egress(struct sk_buff *skb, struct net_device *dev, static void nf_do_netdev_egress(struct sk_buff *skb, struct net_device *dev,
enum nf_dev_hooks hook) enum nf_dev_hooks hook)
{ {
if (__this_cpu_read(nf_dup_skb_recursion) > NF_RECURSION_LIMIT)
goto err;
if (hook == NF_NETDEV_INGRESS && skb_mac_header_was_set(skb)) { if (hook == NF_NETDEV_INGRESS && skb_mac_header_was_set(skb)) {
if (skb_cow_head(skb, skb->mac_len)) { if (skb_cow_head(skb, skb->mac_len))
kfree_skb(skb); goto err;
return;
}
skb_push(skb, skb->mac_len); skb_push(skb, skb->mac_len);
} }
skb->dev = dev; skb->dev = dev;
skb_clear_tstamp(skb); skb_clear_tstamp(skb);
__this_cpu_inc(nf_dup_skb_recursion);
dev_queue_xmit(skb); dev_queue_xmit(skb);
__this_cpu_dec(nf_dup_skb_recursion);
return;
err:
kfree_skb(skb);
} }
void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif) void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif)