From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=217.70.190.124 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793782971; b=rrOaqj+/N87Uj/0xu4TIT7x0MYh80TqvI7/tDIOOSPPchUvU6J7ylUUXQpOv1yVNYIM/ aT9xEV4pbU0TU3n+Vj2LMftfu+ovV6qSTzZMEOuRHk5eeDX5VG99NqQj14OFANsACY/09 byXs4qeY6J6rD92p6gKbsiZkeTSzSPkcy21EiD+x7AFAwUkexKoBhiM9CGCwEnzUnAZV2 UqWQ7McAlPSVYju5sKOyT2iGV8lLVHTHLFbMqItj/T+R9jCWTlsrofDzVuzcaBXudsZ4j 24LkU5KY62kTeLBIlVvTKaHuM3xRpP9R3d4zMzcDm5JNT8jiR4kgK2fpurDMX2Acwzw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793782971; h=DMARC-Filter:DKIM-Signature:Received:From:To:Cc:Subject:Date: Message-ID:X-Mailer:In-Reply-To:References:MIME-Version: Content-Transfer-Encoding:X-Spam-Status:X-Spam-Checker-Version; bh=0GlfH3e3DvVlPjKTJC55ueYHxXbJqUklbkL29/+8PgM=; b=HGEGFAMaYz+mLHdTc1ClcpE9dwvV/acWBSWAyss0TRapSJoxHOpne3T6Rn2GlKKeBw0W KK47BUJ3sDXnhamjpH/ij25TdgL+1iW1E2kztlHbZs4zVksdPmD0mvJcTPNrgvbmPr0Nl q96eiFlqQ3K10py/xNAN21ZSGlH1ITh2y329bkjjaMexB/n4wE2SrEfcHBk/8/bn/+toS TD6YbGc6RAd39i3XqcAaUPQLD+29gkJUYSo8eHs9BC2qsECtXfsIu9gdXNteKHcNKxsPd ZwugrJIl6Z3awuxSLqevlhftwQtJrTLqjWhmtqXkEwKXXExpEPQ4TABV2WhaDZA1ltg== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none header.from=netfilter.org; spf=pass smtp.mailfrom=netfilter.org; dkim=pass header.d=netfilter.org header.i=@netfilter.org header.a=rsa-sha256 header.s=2025 header.b=rNYOOBGZ; arc=none smtp.remote-ip=217.70.190.124 Received: from mail.netfilter.org (mail.netfilter.org [217.70.190.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6321B606A32D; Wed, 4 Nov 2026 09:02:51 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 6321B606A32D 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, unprotected) header.d=netfilter.org header.i=@netfilter.org header.a=rsa-sha256 header.s=2025 header.b=rNYOOBGZ DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netfilter.org; s=2025; t=1793782969; bh=0GlfH3e3DvVlPjKTJC55ueYHxXbJqUklbkL29/+8PgM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rNYOOBGZmMK1i05VB1Erou2GWRbczgBippie1gpKNShZHHEbddfosUxIzJbfdTkjR Ec9bWA092ImL1m70N3on93/uFMfvI2UwAUDO4FZjFLAXQycrLmxNugvaQhBAyNuyve BxmwN5TCkh2g6V5LwtxpwSlTaknwAoU1uyWcebtrmxer+Z2ztVsIFl0Em5U0BXXBjh TEpm9kfWYwDvOi4M2BDU5TSeppaf4Js2/0lpuOQ2t5IJKXYrSsG5zwd8asWv+Hswlk YNhfG3WS52/RWLJ6N8oC+AvqPmBwjVOMNhxCLCxsR4vvcwSvBuqbL+aOuOXYtjWLF5 MKsayOYGW54IQ== Received: from localhost.localdomain (mail-agni [217.70.190.124]) by mail.netfilter.org (Postfix) with ESMTPSA id 2E04E60082; Wed, 4 Nov 2026 10:02:49 +0100 (CET) From: Pablo Neira Ayuso To: netfilter-devel@vger.kernel.org Cc: davem@davemloft.net, netdev@vger.kernel.org, kuba@kernel.org, pabeni@redhat.com, edumazet@kernel.org, horms@kernel.org, fw@strlen.de, ja@ssi.bg Subject: [PATCH net 13/13] netfilter: nat: zero newrange before filling it in Date: Wed, 4 Nov 2026 10:02:24 +0100 Message-ID: <20261104090224.750548-14-pablo@netfilter.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20261104090224.750548-1-pablo@netfilter.org> References: <20261104090224.750548-1-pablo@netfilter.org> X-Mailing-List: netdev@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Florian Westphal nf_nat_masquerade_ipv4(), nf_nat_masquerade_ipv6(), netmap_tg4() and netmap_tg6() each build a stack-local struct nf_nat_range2 from the caller-supplied range, inheriting range->flags unmodified. Two of them only memset() the min_addr/max_addr members, the other two don't memset() anything at all, so newrange.base_proto is left as stack garbage. If the inherited flags include NF_NAT_RANGE_PROTO_OFFSET, nf_nat_l4proto_unique_tuple() reads range->base_proto.all to compute the NAT port offset. Neither the NETMAP nor the MASQUERADE targets mask the flags field in their checkentry callback, so this uninitialized stack value can end up feeding the NAT port selection. The per-member memset()s are not enough: they have to enumerate every field that must be cleared, and base_proto was missed when NF_NAT_RANGE_PROTO_OFFSET/base_proto was added to the struct. memset() the whole struct instead, so every member is covered regardless of which ones get explicitly assigned afterwards. There are other places that miss this, but those hardcode .flags so nat core won't read from the uninitialized fields. C99 initializers would be preferrable, but this is a more intrusive change. Lets followup in nf-next and convert others as well. This is an LLM finding. Fixes: 2eb0f624b709 ("netfilter: add NAT support for shifted portmap ranges") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_nat_masquerade.c | 4 ++-- net/netfilter/xt_NETMAP.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/netfilter/nf_nat_masquerade.c b/net/netfilter/nf_nat_masquerade.c index 4de6e0a51701..c2a85bd84af1 100644 --- a/net/netfilter/nf_nat_masquerade.c +++ b/net/netfilter/nf_nat_masquerade.c @@ -62,8 +62,7 @@ nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum, nat->masq_index = out->ifindex; /* Transfer from original range. */ - memset(&newrange.min_addr, 0, sizeof(newrange.min_addr)); - memset(&newrange.max_addr, 0, sizeof(newrange.max_addr)); + memset(&newrange, 0, sizeof(newrange)); newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; newrange.min_addr.ip = newsrc; newrange.max_addr.ip = newsrc; @@ -242,6 +241,7 @@ nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range, if (nat) nat->masq_index = out->ifindex; + memset(&newrange, 0, sizeof(newrange)); newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; newrange.min_addr.in6 = src; newrange.max_addr.in6 = src; diff --git a/net/netfilter/xt_NETMAP.c b/net/netfilter/xt_NETMAP.c index 7da065a472e0..8bcb3f716d68 100644 --- a/net/netfilter/xt_NETMAP.c +++ b/net/netfilter/xt_NETMAP.c @@ -44,6 +44,7 @@ netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par) netmask.ip6[i]; } + memset(&newrange, 0, sizeof(newrange)); newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; newrange.min_addr = new_addr; newrange.max_addr = new_addr; @@ -91,8 +92,7 @@ netmap_tg4(struct sk_buff *skb, const struct xt_action_param *par) new_ip = ip_hdr(skb)->saddr & ~netmask; new_ip |= mr->range[0].min_ip & netmask; - memset(&newrange.min_addr, 0, sizeof(newrange.min_addr)); - memset(&newrange.max_addr, 0, sizeof(newrange.max_addr)); + memset(&newrange, 0, sizeof(newrange)); newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS; newrange.min_addr.ip = new_ip; newrange.max_addr.ip = new_ip; -- 2.47.3