* [PATCH nf v2] netfilter: nf_reject: initialize IPCB at inet ingress
@ 2026-08-10 16:07 David Lee
0 siblings, 0 replies; only message in thread
From: David Lee @ 2026-08-10 16:07 UTC (permalink / raw)
To: pablo, fw, davem, edumazet, kuba, pabeni
Cc: Kyle Zeng, Dominik 'Disconnect3d' Czarnota, phil, horms,
netfilter-devel, coreteam, netdev, linux-kernel, stable,
David Lee
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;
+ }
+
if (!skb_dst(skb_in) && nf_reject6_fill_skb_dst(skb_in) < 0)
return;
--
2.53.0
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-08-10 16:07 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-10 16:07 [PATCH nf v2] netfilter: nf_reject: initialize IPCB at inet ingress David Lee
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.