All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: David Lee <david.lee@trailofbits.com>
Cc: fw@strlen.de, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com,
	Kyle Zeng <kylebot@openai.com>,
	Dominik 'Disconnect3d' Czarnota
	<dominik.czarnota@trailofbits.com>,
	phil@nwl.cc, horms@kernel.org, netfilter-devel@vger.kernel.org,
	coreteam@netfilter.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH nf v2] netfilter: nf_reject: initialize IPCB at inet ingress
Date: Fri, 21 Aug 2026 15:42:43 +0200	[thread overview]
Message-ID: <aohV0xIb23Pvs7yt@chamomile> (raw)
In-Reply-To: <20260810160703.861885-1-david.lee@trailofbits.com>

On Mon, Aug 10, 2026 at 04:07:03PM +0000, David Lee wrote:
> From: Kyle Zeng <kylebot@openai.com>
> 
> The inet ingress hook runs before ip_rcv_core() and ip6_rcv_core(), so
> neither IPCB nor IP6CB has been initialized when nft_reject_inet passes
> a packet to nf_send_unreach() or nf_send_unreach6(). skb->cb can
> therefore retain metadata from an earlier protocol layer.
> 
> For IPv4, icmp_send() treats IPCB(skb)->opt as parsed IPv4 options.
> Stale option offsets can make __ip_options_echo() copy an
> attacker-controlled length into its 40-byte reply option buffer and
> overflow the stack. On an unpatched v7.2-rc5 kernel, the IPv4
> reproducer produced:
> 
>   BUG: KASAN: stack-out-of-bounds in __ip_options_echo()
>   Write of size 255
> 
> For IPv6, icmpv6_send() consumes IP6CB(skb) as parsed IPv6 metadata. It
> always uses iif for source selection and, when MIP6 is enabled, uses
> dsthao as an extension-header offset. These fields must not be stale.
> 
> For NF_INET_INGRESS, clear the address-family-specific control block
> and restore its input interface before constructing the ICMP error.
> This matches the initialization normally performed by ip_rcv_core()
> and ip6_rcv_core().
> 
> Fixes: 117ca1f8920c ("netfilter: nft_reject_inet: allow to use reject from inet ingress")
> Cc: stable@vger.kernel.org
> Assisted-by: Codex:gpt-5.6-sol Codex:gpt-5.5-cyber
> Signed-off-by: Kyle Zeng <kylebot@openai.com>
> Co-developed-by: David Lee <david.lee@trailofbits.com>
> Signed-off-by: David Lee <david.lee@trailofbits.com>
> ---
> Changes in v2:
> - Initialize IP6CB in nf_send_unreach6() for inet ingress.
> - Preserve the IPv6 input interface before constructing the reply dst.
> 
> v1: https://lore.kernel.org/netfilter-devel/20260804095105.715387-1-david.lee@trailofbits.com/
> 
> Bug found and triaged by OpenAI Security Research and
> validated by Trail of Bits.
> 
> Trail of Bits has an IPv4 reproducer for this bug that triggers the
> KASAN stack-out-of-bounds write in __ip_options_echo() and can share it
> if needed. A separate IPv6 test reaches nf_send_unreach6() from inet
> ingress and confirms that an ICMPv6 unreachable is constructed.
> 
>  net/ipv4/netfilter/nf_reject_ipv4.c | 6 ++++++
>  net/ipv6/netfilter/nf_reject_ipv6.c | 9 +++++++++
>  2 files changed, 15 insertions(+)
> 
> diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c
> index 4626dc46808f..4933f65138d6 100644
> --- a/net/ipv4/netfilter/nf_reject_ipv4.c
> +++ b/net/ipv4/netfilter/nf_reject_ipv4.c
> @@ -355,6 +355,12 @@ void nf_send_unreach(struct sk_buff *skb_in, int code, int hook)
>  	if (!skb_dst(skb_in) && nf_reject_fill_skb_dst(skb_in) < 0)
>  		return;
>  
> +	/* Inet ingress runs before IPv4 initializes IPCB. */
> +	if (hook == NF_INET_INGRESS) {
> +		memset(IPCB(skb_in), 0, sizeof(*IPCB(skb_in)));
> +		IPCB(skb_in)->iif = skb_in->skb_iif;
> +	}
> +
>  	if (skb_csum_unnecessary(skb_in) ||
>  	    !nf_reject_verify_csum(skb_in, dataoff, proto)) {
>  		icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
> diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c
> index ef5b7e85cffa..c36910b8a95a 100644
> --- a/net/ipv6/netfilter/nf_reject_ipv6.c
> +++ b/net/ipv6/netfilter/nf_reject_ipv6.c
> @@ -9,6 +9,7 @@
>  #include <net/ip6_fib.h>
>  #include <net/ip6_checksum.h>
>  #include <net/netfilter/ipv6/nf_reject.h>
> +#include <net/dst_metadata.h>
>  #include <linux/netfilter_ipv6.h>
>  #include <linux/netfilter_bridge.h>
>  
> @@ -440,6 +441,14 @@ void nf_send_unreach6(struct net *net, struct sk_buff *skb_in,
>  	if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
>  		skb_in->dev = net->loopback_dev;
>  
> +	/* Inet ingress runs before IPv6 initializes IP6CB. */
> +	if (hooknum == NF_INET_INGRESS) {
> +		memset(IP6CB(skb_in), 0, sizeof(*IP6CB(skb_in)));
> +		IP6CB(skb_in)->iif = skb_valid_dst(skb_in) ?
> +				     ip6_dst_idev(skb_dst(skb_in))->dev->ifindex :
> +				     skb_in->dev->ifindex;

Why do different? Maybe just use:

        IP6CB(skb_in)->iif = skb_in->skb_iif;

like in the IPv4 chunk?

> +	}
> +
>  	if (!skb_dst(skb_in) && nf_reject6_fill_skb_dst(skb_in) < 0)
>  		return;
>  
> -- 
> 2.53.0
> 

      reply	other threads:[~2026-08-21 13:42 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-10 16:07 [PATCH nf v2] netfilter: nf_reject: initialize IPCB at inet ingress David Lee
2026-08-21 13: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=aohV0xIb23Pvs7yt@chamomile \
    --to=pablo@netfilter.org \
    --cc=coreteam@netfilter.org \
    --cc=davem@davemloft.net \
    --cc=david.lee@trailofbits.com \
    --cc=dominik.czarnota@trailofbits.com \
    --cc=edumazet@google.com \
    --cc=fw@strlen.de \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=kylebot@openai.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=phil@nwl.cc \
    --cc=stable@vger.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 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.