From mboxrd@z Thu Jan 1 00:00:00 1970 Received: by passt.top (Postfix, from userid 1000) id 927A25A0269; Thu, 07 May 2026 06:31:49 +0200 (CEST) From: Stefano Brivio To: passt-dev@passt.top Subject: [PATCH RFT] fwd: Only do inbound IPv6 NAT to map_host_loopback / map_guest_addr with matching scope Date: Thu, 7 May 2026 06:31:49 +0200 Message-ID: <20260507043149.1989693-1-sbrivio@redhat.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: JJMCRTCJEC6U6L3YHCAKKBW5DGEMNCMY X-Message-ID-Hash: JJMCRTCJEC6U6L3YHCAKKBW5DGEMNCMY X-MailFrom: sbrivio@passt.top X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Paul Holzinger X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: I'm sharing this mostly for debugging / investigation of: https://github.com/containers/container-libs/pull/755#issuecomment-4390420134 even though the change is probably correct and needed regardless of that. If we have map_guest_addr or map_host_loopback addresses set for IPv6, before using them for inbound NAT from the host, make sure they match the scope of the original packet, otherwise we might unexpectedly turn global unicast addresses into link-local ones for packets coming from the host itself. Link: https://github.com/containers/container-libs/pull/755#issuecomment-4390420134 Signed-off-by: Stefano Brivio --- fwd.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/fwd.c b/fwd.c index 0697435..d224c0a 100644 --- a/fwd.c +++ b/fwd.c @@ -974,6 +974,20 @@ uint8_t fwd_nat_from_splice(const struct fwd_rule *rule, uint8_t proto, return PIF_HOST; } +/** + * fwd_scope6_match() - Check if the IPv6 scope of two addresses match + * @a: First address + * @b: Second address + * + * Return: true for two IPv6 link-local or both not link-local, false otherwise + * + * NOTE: This currently ignores any other difference in scope + */ +bool fwd_scope6_match(const struct in6_addr *a, const struct in6_addr *b) +{ + return IN6_IS_ADDR_LINKLOCAL(a) == IN6_IS_ADDR_LINKLOCAL(b); +} + /** * nat_inbound() - Apply address translation for inbound (HOST to TAP) * @c: Execution context @@ -993,13 +1007,15 @@ bool nat_inbound(const struct ctx *c, const union inany_addr *addr, /* Specifically 127.0.0.1, not 127.0.0.0/8 */ *translated = inany_from_v4(c->ip4.map_host_loopback); } else if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.map_host_loopback) && - inany_equals6(addr, &in6addr_loopback)) { + inany_equals6(addr, &in6addr_loopback) && + fwd_scope6_match(&addr->a6, &c->ip6.map_host_loopback)) { translated->a6 = c->ip6.map_host_loopback; } else if (!IN4_IS_ADDR_UNSPECIFIED(&c->ip4.map_guest_addr) && inany_equals4(addr, &c->ip4.addr)) { *translated = inany_from_v4(c->ip4.map_guest_addr); } else if (!IN6_IS_ADDR_UNSPECIFIED(&c->ip6.map_guest_addr) && - inany_equals6(addr, &c->ip6.addr)) { + inany_equals6(addr, &c->ip6.addr) && + fwd_scope6_match(&addr->a6, &c->ip6.map_guest_addr)) { translated->a6 = c->ip6.map_guest_addr; } else if (fwd_guest_accessible(c, addr)) { *translated = *addr; -- 2.43.0