From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail.netfilter.org (mail.netfilter.org [217.70.190.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5689B3E276B; Tue, 28 Apr 2026 10:02:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.190.124 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777370529; cv=none; b=PWd254C5aHad+gZcZw3/QfUvioEHybQ5txMkzZtsfrUju2OStek0jrIaRqaVblTTv1s9pGxbUjE7Cyzh5CtenzMdNgeGFoqKlCz8fehZDkMuukFPu5p3RqzVF0rgZjr0ciQRRNT6P+jC51LcgjJKHDS11JzBgBcYhu7CM6fV33I= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777370529; c=relaxed/simple; bh=7wZnek3T2WzkDUClNEn0Q4evHVM7o6mrY/FfK1YGXAs=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=EcwXk62Smy6N+veuvBpW0D20QncBq/vvs6C4QqGEAeUbCwIFgOBv92Oo3ay9UuFZqaN4JuiTSfpmXgt5FFL90izsISUNlUjP+AdiPfwgM5BEVzwylyGWfEB1q7eh6E3SYW/5qH745fzUtkrMRVH4cml8/1/wECGOjXNfPyKvmGs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=netfilter.org; spf=pass smtp.mailfrom=netfilter.org; dkim=pass (2048-bit key) header.d=netfilter.org header.i=@netfilter.org header.b=vZ+vV/f/; arc=none smtp.client-ip=217.70.190.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=netfilter.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=netfilter.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=netfilter.org header.i=@netfilter.org header.b="vZ+vV/f/" Received: from netfilter.org (mail-agni [217.70.190.124]) by mail.netfilter.org (Postfix) with UTF8SMTPSA id EF79060254; Tue, 28 Apr 2026 12:02:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netfilter.org; s=2025; t=1777370522; bh=mX1aKSwyKUDAIurw50IRSKGuAlkO8nsP16/ASR0ldxs=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=vZ+vV/f/JRxh0cPRGa3wlOvfVbLbtsfxjccG0rLLOfkFly+ptt3Hr2F08V7vcuJtT Bi0Pf+eDbdOxgxv+MQiFSGOAqeOfBvvwNgsBU1tHuy9jU866+0p1iaGscWN0SOkRZs EhXE++jtayzlJt701JfwctW4Lzp/dWNw3ZvDFh5oD1vdNqzA73xalIp4IE235lFXeA Xhj4iEmbhVopTbpWNdl/z1q4f0nUEal3n7lp0ymDiQSSvqeyZOTGn47xG26KsfGEy7 VJc+NDuOng9gTbNohkziirJf7igXPXzGtzJZiu6a0qlSH3Rc2vUq6FSl4KBHLwzyni IwvG20crSREsg== Date: Tue, 28 Apr 2026 12:01:59 +0200 From: Pablo Neira Ayuso To: Mathias Krause Cc: netfilter-devel@vger.kernel.org, Florian Westphal , netdev@vger.kernel.org Subject: Re: [PATCH net] netfilter: nf_nat: avoid invalid nat_net pointer use on failed nf_nat_init() Message-ID: References: <20260428090917.3851366-1-minipli@grsecurity.net> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit 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: > > […] 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 > > ================================================================== > > 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 > --- > 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 >