From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Sayooj K Karun <sayooj@aerlync.com>
Cc: netfilter-devel@vger.kernel.org, Florian Westphal <fw@strlen.de>,
Phil Sutter <phil@nwl.cc>,
netdev@vger.kernel.org, edumazet@google.com
Subject: Re: [PATCH nf-next] netfilter: nf_reject_ipv6: do not reject ICMPv6 Redirect with an ICMPv6 error
Date: Mon, 8 Jun 2026 13:42:04 +0200 [thread overview]
Message-ID: <aiaqjP8q-UQ0YUK0@chamomile> (raw)
In-Reply-To: <20260608103155.8339-1-sayooj@aerlync.com>
On Mon, Jun 08, 2026 at 04:01:55PM +0530, Sayooj K Karun wrote:
> While fixing is_ineligible() for the L3 reject path, the bridge/netdev
> reject path was found to have the same defect. RFC 4443 section 2.4(e.2)
> mandates that an ICMPv6 error MUST NOT be originated in response to an
> ICMPv6 Redirect message (type 137).
>
> There are two IPv6 reject paths, and they suppress this in different
> places. The L3 path (ip6t_REJECT / nft_reject -> nf_send_unreach6())
> goes through icmpv6_send(), where is_ineligible() decides whether the
> triggering packet may generate an error; a companion fix makes that gate
> drop errors in response to a Redirect. The bridge/netdev path
> (nft_reject_bridge / nft_reject_netdev -> nf_reject_skb_v6_unreach())
> builds the ICMPv6 packet itself and never reaches is_ineligible().
> Its local guard, nf_skb_is_icmp6_unreach(), only matched
> ICMPV6_DEST_UNREACH and let every other type through,
> including Redirect.
>
> A triggerable scenario: a bridge or netdev firewall with a REJECT rule
> applied to incoming ICMPv6 traffic (e.g., dropping Redirects from an
> untrusted segment). When the Redirect hits the REJECT rule,
> nf_reject_skb_v6_unreach() builds and transmits a Destination Unreachable
> in response. Without this fix the guard lets the Redirect through and the
> error is erroneously sent, violating the RFC.
>
> Extend the guard, renamed nf_skb_is_icmp6_unreach_or_redirect(), to also
> match NDISC_REDIRECT so that Redirect packets are skipped and both reject
> paths behave consistently.
>
> Link: https://lore.kernel.org/ah_hYJa3byoUyose@chamomile
> Signed-off-by: Sayooj K Karun <sayooj@aerlync.com>
> ---
> net/ipv6/netfilter/nf_reject_ipv6.c | 14 ++++++++++----
> 1 file changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c
> index ef5b7e85c..d4eec8d9a 100644
> --- a/net/ipv6/netfilter/nf_reject_ipv6.c
> +++ b/net/ipv6/netfilter/nf_reject_ipv6.c
> @@ -8,6 +8,7 @@
> #include <net/ip6_route.h>
> #include <net/ip6_fib.h>
> #include <net/ip6_checksum.h>
> +#include <net/ndisc.h>
> #include <net/netfilter/ipv6/nf_reject.h>
> #include <linux/netfilter_ipv6.h>
> #include <linux/netfilter_bridge.h>
> @@ -104,7 +105,7 @@ struct sk_buff *nf_reject_skb_v6_tcp_reset(struct net *net,
> }
> EXPORT_SYMBOL_GPL(nf_reject_skb_v6_tcp_reset);
>
> -static bool nf_skb_is_icmp6_unreach(const struct sk_buff *skb)
> +static bool nf_skb_is_icmp6_unreach_or_redirect(const struct sk_buff *skb)
> {
> const struct ipv6hdr *ip6h = ipv6_hdr(skb);
> u8 proto = ip6h->nexthdr;
> @@ -127,7 +128,7 @@ static bool nf_skb_is_icmp6_unreach(const struct sk_buff *skb)
> if (!tp)
> return false;
>
> - return *tp == ICMPV6_DEST_UNREACH;
> + return *tp == ICMPV6_DEST_UNREACH || *tp == NDISC_REDIRECT;
> }
>
> struct sk_buff *nf_reject_skb_v6_unreach(struct net *net,
> @@ -143,8 +144,13 @@ struct sk_buff *nf_reject_skb_v6_unreach(struct net *net,
> if (!nf_reject_ip6hdr_validate(oldskb))
> return NULL;
>
> - /* Don't reply to ICMPV6_DEST_UNREACH with ICMPV6_DEST_UNREACH */
> - if (nf_skb_is_icmp6_unreach(oldskb))
> + /* Don't reply to ICMPV6_DEST_UNREACH with ICMPV6_DEST_UNREACH, and
> + * per RFC 4443 section 2.4(e.2) never originate an ICMPv6 error in
> + * response to an ICMPv6 Redirect. The L3 reject path enforces this
> + * via icmpv6_send()/is_ineligible(); this bridge/netdev path builds
> + * the packet itself, so it must check explicitly.
Please, shorter comment. With all these AI generated comments,
codebase will bloat soon. Comments are usually reserve to non-obvious
stuff IIRC, this extra validation can be possibly documented in the
new nf_skb_is_icmp6_unreach_or_redirect_or_something_else().
> + */
> + if (nf_skb_is_icmp6_unreach_or_redirect(oldskb))
Please, use more generic function:
nf_skb_icmp6_is_valid()
so this can grown with any other future extension without adding
another _or_something_else() to the function name.
Thanks.
> return NULL;
>
> /* Include "As much of invoking packet as possible without the ICMPv6
> --
> 2.54.0
>
prev parent reply other threads:[~2026-06-08 11:42 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-08 10:31 [PATCH nf-next] netfilter: nf_reject_ipv6: do not reject ICMPv6 Redirect with an ICMPv6 error Sayooj K Karun
2026-06-08 11:42 ` Pablo Neira Ayuso [this message]
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=aiaqjP8q-UQ0YUK0@chamomile \
--to=pablo@netfilter.org \
--cc=edumazet@google.com \
--cc=fw@strlen.de \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=phil@nwl.cc \
--cc=sayooj@aerlync.com \
/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