From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Weiming Shi <bestswngs@gmail.com>
Cc: Florian Westphal <fw@strlen.de>,
"David S . Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Phil Sutter <phil@nwl.cc>, Simon Horman <horms@kernel.org>,
netfilter-devel@vger.kernel.org, coreteam@netfilter.org,
netdev@vger.kernel.org, Xiang Mei <xmei5@asu.edu>
Subject: Re: [PATCH v2] netfilter: nft_fwd_netdev: use recursion counter in neigh egress path
Date: Thu, 9 Apr 2026 13:21:24 +0200 [thread overview]
Message-ID: <adeLtBMyR3KZInDW@chamomile> (raw)
In-Reply-To: <adeIF7ZsJsZsgwQy@chamomile>
On Thu, Apr 09, 2026 at 01:06:03PM +0200, Pablo Neira Ayuso wrote:
> On Thu, Apr 09, 2026 at 06:49:12PM +0800, Weiming Shi wrote:
> > nft_fwd_neigh can be used in egress chains (NF_NETDEV_EGRESS). When the
> > forwarding rule targets the same device or two devices forward to each
> > other, neigh_xmit() triggers dev_queue_xmit() which re-enters
> > nf_hook_egress(), causing infinite recursion and stack overflow.
> >
> > Move the nf_get_nf_dup_skb_recursion() accessor and NF_RECURSION_LIMIT
> > to the shared header nf_dup_netdev.h as a static inline, so that
> > nft_fwd_netdev can use the recursion counter directly without exported
> > function call overhead. Guard neigh_xmit() with the same recursion
> > limit already used in nf_do_netdev_egress().
> >
> > Fixes: f87b9464d152 ("netfilter: nft_fwd_netdev: Support egress hook")
>
> I would just restrict this "feature", I don't see a point in allowing
> this from egress?
Hm, actually this can be combined with if0 device, fixing it makes sense.
> > Reported-by: Xiang Mei <xmei5@asu.edu>
> > Signed-off-by: Weiming Shi <bestswngs@gmail.com>
> > ---
> > include/net/netfilter/nf_dup_netdev.h | 13 +++++++++++++
> > net/netfilter/nf_dup_netdev.c | 16 ----------------
> > net/netfilter/nft_fwd_netdev.c | 7 +++++++
> > 3 files changed, 20 insertions(+), 16 deletions(-)
> >
> > diff --git a/include/net/netfilter/nf_dup_netdev.h b/include/net/netfilter/nf_dup_netdev.h
> > index b175d271aec9..609bcf422a9b 100644
> > --- a/include/net/netfilter/nf_dup_netdev.h
> > +++ b/include/net/netfilter/nf_dup_netdev.h
> > @@ -3,10 +3,23 @@
> > #define _NF_DUP_NETDEV_H_
> >
> > #include <net/netfilter/nf_tables.h>
> > +#include <linux/netdevice.h>
> > +#include <linux/sched.h>
> >
> > void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif);
> > void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif);
> >
> > +#define NF_RECURSION_LIMIT 2
> > +
> > +static inline u8 *nf_get_nf_dup_skb_recursion(void)
> > +{
> > +#ifndef CONFIG_PREEMPT_RT
> > + return this_cpu_ptr(&softnet_data.xmit.nf_dup_skb_recursion);
> > +#else
> > + return ¤t->net_xmit.nf_dup_skb_recursion;
> > +#endif
> > +}
> > +
> > struct nft_offload_ctx;
> > struct nft_flow_rule;
> >
> > diff --git a/net/netfilter/nf_dup_netdev.c b/net/netfilter/nf_dup_netdev.c
> > index fab8b9011098..a958a1b0c5be 100644
> > --- a/net/netfilter/nf_dup_netdev.c
> > +++ b/net/netfilter/nf_dup_netdev.c
> > @@ -13,22 +13,6 @@
> > #include <net/netfilter/nf_tables_offload.h>
> > #include <net/netfilter/nf_dup_netdev.h>
> >
> > -#define NF_RECURSION_LIMIT 2
> > -
> > -#ifndef CONFIG_PREEMPT_RT
> > -static u8 *nf_get_nf_dup_skb_recursion(void)
> > -{
> > - return this_cpu_ptr(&softnet_data.xmit.nf_dup_skb_recursion);
> > -}
> > -#else
> > -
> > -static u8 *nf_get_nf_dup_skb_recursion(void)
> > -{
> > - return ¤t->net_xmit.nf_dup_skb_recursion;
> > -}
> > -
> > -#endif
> > -
> > static void nf_do_netdev_egress(struct sk_buff *skb, struct net_device *dev,
> > enum nf_dev_hooks hook)
> > {
> > diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c
> > index 152a9fb4d23a..492bb599a499 100644
> > --- a/net/netfilter/nft_fwd_netdev.c
> > +++ b/net/netfilter/nft_fwd_netdev.c
> > @@ -141,13 +141,20 @@ static void nft_fwd_neigh_eval(const struct nft_expr *expr,
> > goto out;
> > }
> >
> > + if (*nf_get_nf_dup_skb_recursion() > NF_RECURSION_LIMIT) {
> > + verdict = NF_DROP;
> > + goto out;
> > + }
> > +
> > dev = dev_get_by_index_rcu(nft_net(pkt), oif);
> > if (dev == NULL)
> > return;
> >
> > skb->dev = dev;
> > skb_clear_tstamp(skb);
> > + (*nf_get_nf_dup_skb_recursion())++;
> > neigh_xmit(neigh_table, dev, addr, skb);
> > + (*nf_get_nf_dup_skb_recursion())--;
> > out:
> > regs->verdict.code = verdict;
> > }
> > --
> > 2.43.0
> >
> >
next prev parent reply other threads:[~2026-04-09 11:21 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-09 10:49 [PATCH v2] netfilter: nft_fwd_netdev: use recursion counter in neigh egress path Weiming Shi
2026-04-09 11:05 ` Pablo Neira Ayuso
2026-04-09 11:21 ` Pablo Neira Ayuso [this message]
2026-04-09 15:06 ` Weiming Shi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=adeLtBMyR3KZInDW@chamomile \
--to=pablo@netfilter.org \
--cc=bestswngs@gmail.com \
--cc=coreteam@netfilter.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=fw@strlen.de \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=phil@nwl.cc \
--cc=xmei5@asu.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.