All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Mathias Krause <minipli@grsecurity.net>
Cc: netfilter-devel@vger.kernel.org, Florian Westphal <fw@strlen.de>,
	netdev@vger.kernel.org
Subject: Re: [PATCH net] netfilter: nf_nat: avoid invalid nat_net pointer use on failed nf_nat_init()
Date: Tue, 28 Apr 2026 12:01:59 +0200	[thread overview]
Message-ID: <afCFlxjOiEs2ouKY@chamomile> (raw)
In-Reply-To: <20260428090917.3851366-1-minipli@grsecurity.net>

On Tue, Apr 28, 2026 at 11:09:17AM +0200, Mathias Krause wrote:
> We ran into below KASAN splat, which is mostly uninteresting, beside
> for having nf_nat_register_fn() in the call chain as a cause for the
> offending access:
> 
> ==================================================================
> BUG: KASAN: slab-out-of-bounds in nf_nat_register_fn+0x5f9/0x640
> Read of size 8 at addr ffff890031e54c20 by task iptables/9510
> 
> CPU: 0 UID: 0 PID: 9510 Comm: iptables Not tainted 6.18.18-grsec-full-20260320181326 #1 PREEMPT(voluntary)
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
> Call Trace:
>  <TASK>
>  […] dump_stack_lvl+0xee/0x160 ffff88004117eeb8
>  […] print_report+0x6e/0x640 ffff88004117eee0
>  […] ? __phys_addr+0x8e/0x140 ffff88004117eef0
>  […] ? kasan_addr_to_slab+0x51/0xe0 ffff88004117ef08
>  […] ? complete_report_info+0xec/0x1c0 ffff88004117ef20
>  […] ? nf_nat_register_fn+0x5f9/0x640 ffff88004117ef48
>  […] kasan_report+0xbc/0x140 ffff88004117ef50
>  […] ? nf_nat_register_fn+0x5f9/0x640 ffff88004117ef90
>  […] nf_nat_register_fn+0x5f9/0x640 ffff88004117eff8
>  […] ? nf_nat_icmp_reply_translation+0x6e0/0x6e0 ffff88004117f070
>  […] nf_tables_register_hook.part.0+0xa0/0x220 ffff88004117f080
>  […] nf_tables_addchain.constprop.0+0x1054/0x1fc0 ffff88004117f0b8
>  […] ? nft_chain_lookup.part.0+0x4ce/0xac0 ffff88004117f130
>  […] ? nf_tables_abort+0x3d80/0x3d80 ffff88004117f190
>  […] ? nf_tables_dumpreset_obj+0x100/0x100 ffff88004117f1c8
>  […] ? nft_table_lookup.part.0+0x255/0x300 ffff88004117f310
>  […] ? nf_tables_newchain+0x21a4/0x2fa0 ffff88004117f358
>  […] nf_tables_newchain+0x21a4/0x2fa0 ffff88004117f360
>  […] ? nf_tables_addchain.constprop.0+0x1fc0/0x1fc0 ffff88004117f458
>  […] ? nla_get_range_signed+0x4a0/0x4a0 ffff88004117f488
>  […] ? lock_acquire+0x16f/0x320 ffff88004117f490
>  […] ? find_held_lock+0x3b/0xe0 ffff88004117f4b0
>  […] ? __nla_parse+0x45/0x80 ffff88004117f500
>  […] nfnetlink_rcv_batch+0xbca/0x19a0 ffff88004117f550
>  […] ? nfnetlink_net_exit_batch+0x120/0x120 ffff88004117f618
>  […] ? __sanitizer_cov_trace_switch+0x63/0xe0 ffff88004117f720
>  […] ? gr_acl_handle_mmap+0x1c4/0x320 ffff88004117f7c0
>  […] ? nla_get_range_signed+0x4a0/0x4a0 ffff88004117f7e8
>  […] ? gr_is_capable+0x6f/0xe0 ffff88004117f830
>  […] ? __nla_parse+0x45/0x80 ffff88004117f860
>  […] ? skb_pull+0x103/0x1a0 ffff88004117f880
>  […] nfnetlink_rcv+0x3db/0x4a0 ffff88004117f8b0
>  […] ? nfnetlink_rcv_batch+0x19a0/0x19a0 ffff88004117f8d8
>  […] ? netlink_lookup+0xe2/0x240 ffff88004117f900
>  […] netlink_unicast+0x74b/0xb00 ffff88004117f930
>  […] ? netlink_attachskb+0xb20/0xb20 ffff88004117f980
>  […] ? __check_object_size+0x3e/0xaa0 ffff88004117f998
>  […] ? security_netlink_send+0x51/0x160 ffff88004117f9c8
>  […] netlink_sendmsg+0xa03/0x1200 ffff88004117f9f8
>  […] ? netlink_unicast+0xb00/0xb00 ffff88004117fa70
>  […] ? netlink_unicast+0xb00/0xb00 ffff88004117fac8
>  […] ? ____sys_sendmsg+0xe2a/0x1040 ffff88004117faf8
>  […] ____sys_sendmsg+0xe2a/0x1040 ffff88004117fb00
>  […] ? kernel_recvmsg+0x300/0x300 ffff88004117fb60
>  […] ? reacquire_held_locks+0xe9/0x260 ffff88004117fbc8
>  […] ___sys_sendmsg+0x138/0x200 ffff88004117fbf8
>  […] ? do_recvmmsg+0x7e0/0x7e0 ffff88004117fc30
>  […] ? lockdep_hardirqs_on_prepare+0x101/0x1e0 ffff88004117fc50
>  […] ? lock_acquire+0x16f/0x320 ffff88004117fd20
>  […] ? lock_acquire+0x16f/0x320 ffff88004117fd58
>  […] ? find_held_lock+0x3b/0xe0 ffff88004117fd70
>  […] __sys_sendmsg+0x17a/0x260 ffff88004117fdc8
>  […] ? __sys_sendmsg_sock+0x80/0x80 ffff88004117fdf0
>  […] ? syscall_trace_enter+0x15e/0x2c0 ffff88004117fe98
>  […] do_syscall_64+0x7d/0x400 ffff88004117fec8
>  […] entry_SYSCALL_64_safe_stack+0x4a/0x60 ffff88004117fef8
>  </TASK>
> ==================================================================
> 
> The out-of-bounds report, though, is a red herring as it is for an
> access that shouldn't have happened in the first place.
> 
> When nf_nat_init() fails to register its BPF kfuncs, it'll unwind and,
> among others, call unregister_pernet_subsys() to deregister its per-net
> ops. This makes the previously allocated net id available for reuse by
> the next caller of register_pernet_subsys(), in our case, synproxy.
> However, 'nat_net_id' will still hold the previously allocated value.
> 
> If nf_nat.o gets build as a module, all this doesn't matter. A failed
> initialization routine makes the module fail to load and any dependent
> module won't be able to load either. However, if nf_nat.o is built-in,
> a failing init won't /completely/ make its functionality unavailable to
> dependent modules, namely the code and static data is still there, free
> to be called by modules like nft_chain_nat.ko.
> 
> Case in point, nft_chain_nat registers hooks that'll call into nf_nat
> which, in our case, failed to initialize and therefore won't have a
> valid net id nor related net_nat object any more.
> 
> Code in nf_nat, namely nf_nat_register_fn() and nf_nat_unregister_fn(),
> still making use of the reallocated net id, lead to a type confusion as
> the call to net_generic() will no longer return memory belonging to an
> object suited to fit 'struct nat_net' but 'struct synproxy_net' instead.
> The latter is only 24 bytes on 64-bit systems, much smaller than struct
> nat_net which is 176 bytes, perfectly explaining the OOB KASAN report.
> 
> Detect and handle a failed nf_nat_init() by testing the 'nf_nat_hook'
> pointer which will be reset to NULL on initialization errors to prevent
> the usage of an invalid nat_net pointer.
> 
> As this check is only needed when nf_nat.o is built-in, guard it by
> '#ifndef MODULE...'.
> 
> Fixes: cbc1dd5b659f ("netfilter: nf_nat: Fix possible memory leak in nf_nat_init()")
> Signed-off-by: Mathias Krause <minipli@grsecurity.net>
> ---
>  net/netfilter/nf_nat_core.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
> index 3b5434e4ec9c..76a150b9d418 100644
> --- a/net/netfilter/nf_nat_core.c
> +++ b/net/netfilter/nf_nat_core.c
> @@ -1187,6 +1187,16 @@ int nf_nat_register_fn(struct net *net, u8 pf, const struct nf_hook_ops *ops,
>  	struct nf_hook_ops *nat_ops;
>  	int i, ret;
>  
> +#ifndef MODULE
> +	/* If nf_nat_core is built-in and nf_nat_init() fails, dependent
> +	 * modules like nft_chain_nat.ko may still call this function.
> +	 * However, nat_net would be invalid, likely pointing to some other
> +	 * per-net structure.

Hm, if nf_nat_init() fails, then nft_chain_nat should fail to load.

Maybe there is a different way to validate this dependency?

> +	 */
> +	if (WARN_ON_ONCE(!nf_nat_hook))
> +		return -EOPNOTSUPP;
> +#endif
> +
>  	if (WARN_ON_ONCE(pf >= ARRAY_SIZE(nat_net->nat_proto_net)))
>  		return -EINVAL;
>  
> -- 
> 2.47.3
> 

  reply	other threads:[~2026-04-28 10:02 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-28  9:09 [PATCH net] netfilter: nf_nat: avoid invalid nat_net pointer use on failed nf_nat_init() Mathias Krause
2026-04-28 10:01 ` Pablo Neira Ayuso [this message]
2026-04-28 11:48   ` Mathias Krause

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=afCFlxjOiEs2ouKY@chamomile \
    --to=pablo@netfilter.org \
    --cc=fw@strlen.de \
    --cc=minipli@grsecurity.net \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@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.