From: Ido Schimmel <idosch@nvidia.com>
To: Leonard Lausen <leonard@lausen.nl>
Cc: netdev@vger.kernel.org, David Ahern <dsahern@kernel.org>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@kernel.org>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>,
Pablo Neira Ayuso <pablo@netfilter.org>,
Florian Westphal <fw@strlen.de>, Phil Sutter <phil@nwl.cc>,
Shuah Khan <shuah@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
netfilter-devel@vger.kernel.org, coreteam@netfilter.org,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH net v2 1/2] ipv6: honor prefix-length suppression in raw FIB lookups
Date: Sun, 15 Nov 2026 17:46:39 +0200 [thread overview]
Message-ID: <20261115154639.GA4121811@shredder> (raw)
In-Reply-To: <20261115114434.10343-4-leonard@lausen.nl>
On Sun, Nov 15, 2026 at 11:44:32AM +0000, Leonard Lausen wrote:
> IPv6 raw FIB lookups populate f6i and nh in fib6_result, but not rt6.
> fib6_rule_suppress() only examines rt6, so fib6_lookup() ignores
> suppress_prefixlength.
>
> With a policy rule that suppresses the main-table default before looking
> in a VPN table, an ordinary route lookup selects the VPN while an nftables
> FIB lookup returns the suppressed default. Strict reverse-path filtering
> can then drop replies arriving over the VPN.
>
> For raw lookups, evaluate suppress_prefixlength against the FIB entry's
> destination prefix length. Preserve results marked RTF_REJECT: raw lookups
> can return zero with a rejection encoded in the result, while dst-based
> lookups return an error and skip suppression. Check the result flags so
> blackhole nexthop objects are covered as well.
>
> Keep the dst-based path unchanged. Raw suppress_ifgroup handling also
> remains unchanged because the table lookup's nexthop need not be the
> final multipath selection.
Never heard of "IPv6 raw FIB lookups". This commit message [1] is easier
to understand.
BTW, I think that fib6_rule_suppress() should always work on the FIB
entry ('rt->from') instead of the dst entry. Currently, if the default
route has an exception for the destination (e.g., via PMTU), then the
default route will not be suppressed since 'rt->rt6i_dst.plen' is 128.
I will add it to my TODO list. This patch doesn't need to fix it.
>
> Fixes: 138118ec96cb ("net/ipv6: Add fib6_lookup")
Should be:
Fixes: 1c32b24c234b ("netfilter: nft_fib_ipv6: switch to fib6_lookup")
The tag should point to the commit that introduced the regression.
> Link: https://github.com/firewalld/firewalld/issues/1600
> Assisted-by: LLM
Please remove this tag. See commit 1e035297ffda ("docs: remove
Assisted-by references").
> Signed-off-by: Leonard Lausen <leonard@lausen.nl>
> ---
> Investigated with AI assistance after VPN failures. Reproduced on
> unmodified v7.4-rc2 and verified with nft_fib.sh on the rebuilt kernel.
>
> net/ipv6/fib6_rules.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
> index 0ffd7b47a046..ceb4180bcf2f 100644
> --- a/net/ipv6/fib6_rules.c
> +++ b/net/ipv6/fib6_rules.c
> @@ -283,9 +283,16 @@ INDIRECT_CALLABLE_SCOPE bool fib6_rule_suppress(struct fib_rule *rule,
> struct fib_lookup_arg *arg)
> {
> struct fib6_result *res = arg->result;
> - struct rt6_info *rt = res->rt6;
> + struct rt6_info *rt;
Unnecessary change, please drop. It also breaks reverse xmas tree:
https://docs.kernel.org/next/process/maintainer-netdev.html#local-variable-ordering-reverse-xmas-tree-rcs
> struct net_device *dev = NULL;
>
> + if (arg->lookup_ptr == fib6_table_lookup) {
> + /* Raw lookups report reject routes without an error. */
/* fib6_table_lookup() returns 0 for reject routes. */
> + return !(res->fib6_flags & RTF_REJECT) &&
> + res->f6i->fib6_dst.plen <= rule->suppress_prefixlen;
> + }
> +
> + rt = res->rt6;
> if (!rt)
> return false;
>
> --
> 2.55.0
>
[1]
ipv6: Honor suppress_prefixlength in fib6_lookup()
When custom FIB rules are configured, fib6_lookup() performs the lookup
via fib6_rule_action_alt() which calls fib6_table_lookup() and only
populates the f6i, nh, fib6_flags and fib6_type fields of the FIB
result. However, fib6_rule_suppress() only examines the rt6 field, which
is only populated when the lookup is performed via one of the callers of
fib6_rule_lookup() such as ip6_route_output(). As a result,
fib6_lookup() ignores suppress_prefixlength.
This was not a problem for nftables until commit 1c32b24c234b
("netfilter: nft_fib_ipv6: switch to fib6_lookup") switched the FIB
expression from ip6_route_lookup() / nf_ip6_route() to fib6_lookup().
Since then, with a rule that suppresses the default route in the main
table before looking up a VPN table (as commonly configured for
WireGuard), the FIB expression returns the suppressed default route
instead of the VPN route. Strict reverse path filtering then drops
replies received over the VPN.
Fix by evaluating suppress_prefixlength against the prefix length of
the FIB entry when the lookup is performed via fib6_lookup().
fib_rules_lookup() only invokes the suppress callback when the rule
action returns 0. Unlike __fib6_rule_action(), fib6_rule_action_alt()
returns 0 for reject routes and instead sets RTF_REJECT in the result.
Do not suppress such routes so that they continue to terminate the
lookup, as with ip6_route_output() and IPv4. Check the flags in the
result rather than in the FIB entry so that blackhole nexthop objects
are also covered.
suppress_ifgroup is not handled since fib6_table_lookup() does not
perform multipath selection and the nexthop it returns might not be the
one that is eventually used.
next prev parent reply other threads:[~2026-11-15 15:46 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-15 11:44 [PATCH net v2 0/2] ipv6: honor prefix-length suppression in raw FIB lookups Leonard Lausen
2026-11-15 11:44 ` [PATCH net v2 1/2] " Leonard Lausen
2026-11-15 15:46 ` Ido Schimmel [this message]
2026-11-15 11:44 ` [PATCH net v2 2/2] selftests: netfilter: cover IPv6 FIB prefix suppression Leonard Lausen
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=20261115154639.GA4121811@shredder \
--to=idosch@nvidia.com \
--cc=coreteam@netfilter.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@kernel.org \
--cc=fw@strlen.de \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=leonard@lausen.nl \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pablo@netfilter.org \
--cc=phil@nwl.cc \
--cc=shuah@kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox