From ad4d9b046482a3a3fef19388a0d692ff4ebbe730 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Tue, 28 May 2024 13:26:31 -0700 Subject: [PATCH] net/netip: check if address is v6 mapped in Is methods In all of the Is* methods, check if the address is a v6 mapped v4 address, and unmap it if so. Thanks to Enze Wang of Alioth (@zer0yu) and Jianjun Chen of Zhongguancun Lab (@chenjj) for reporting this issue. Fixes #67680 Fixes CVE-2024-24790 Change-Id: I6bd03ca1a5d93a0b59027d861c84060967b265b0 Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1460 Reviewed-by: Russ Cox Reviewed-by: Damien Neil Reviewed-on: https://go-review.googlesource.com/c/go/+/590316 Reviewed-by: David Chase Auto-Submit: Michael Knyszek LUCI-TryBot-Result: Go LUCI --- src/net/netip/inlining_test.go | 2 -- src/net/netip/netip.go | 26 +++++++++++++++++- src/net/netip/netip_test.go | 50 +++++++++++++++++++++++++++++++--- 3 files changed, 71 insertions(+), 7 deletions(-) diff --git a/src/net/netip/inlining_test.go b/src/net/netip/inlining_test.go index f5eb30df90..afd3e32bd2 100644 --- a/src/net/netip/inlining_test.go +++ b/src/net/netip/inlining_test.go @@ -36,8 +36,6 @@ func TestInlining(t *testing.T) { "Addr.Is4", "Addr.Is4In6", "Addr.Is6", - "Addr.IsLoopback", - "Addr.IsMulticast", "Addr.IsInterfaceLocalMulticast", "Addr.IsValid", "Addr.IsUnspecified", diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index 4b0a61dd98..57063eeb71 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -516,6 +516,10 @@ func (ip Addr) hasZone() bool { // IsLinkLocalUnicast reports whether ip is a link-local unicast address. func (ip Addr) IsLinkLocalUnicast() bool { + if ip.Is4In6() { + ip = ip.Unmap() + } + // Dynamic Configuration of IPv4 Link-Local Addresses // https://datatracker.ietf.org/doc/html/rfc3927#section-2.1 if ip.Is4() { @@ -531,6 +535,10 @@ func (ip Addr) IsLinkLocalUnicast() bool { // IsLoopback reports whether ip is a loopback address. func (ip Addr) IsLoopback() bool { + if ip.Is4In6() { + ip = ip.Unmap() + } + // Requirements for Internet Hosts -- Communication Layers (3.2.1.3 Addressing) // https://datatracker.ietf.org/doc/html/rfc1122#section-3.2.1.3 if ip.Is4() { @@ -546,6 +554,10 @@ func (ip Addr) IsLoopback() bool { // IsMulticast reports whether ip is a multicast address. func (ip Addr) IsMulticast() bool { + if ip.Is4In6() { + ip = ip.Unmap() + } + // Host Extensions for IP Multicasting (4. HOST GROUP ADDRESSES) // https://datatracker.ietf.org/doc/html/rfc1112#section-4 if ip.Is4() { @@ -564,7 +576,7 @@ func (ip Addr) IsMulticast() bool { func (ip Addr) IsInterfaceLocalMulticast() bool { // IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses) // https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1 - if ip.Is6() { + if ip.Is6() && !ip.Is4In6() { return ip.v6u16(0)&0xff0f == 0xff01 } return false // zero value @@ -572,6 +584,10 @@ func (ip Addr) IsInterfaceLocalMulticast() bool { // IsLinkLocalMulticast reports whether ip is a link-local multicast address. func (ip Addr) IsLinkLocalMulticast() bool { + if ip.Is4In6() { + ip = ip.Unmap() + } + // IPv4 Multicast Guidelines (4. Local Network Control Block (224.0.0/24)) // https://datatracker.ietf.org/doc/html/rfc5771#section-4 if ip.Is4() { @@ -600,6 +616,10 @@ func (ip Addr) IsGlobalUnicast() bool { return false } + if ip.Is4In6() { + ip = ip.Unmap() + } + // Match package net's IsGlobalUnicast logic. Notably private IPv4 addresses // and ULA IPv6 addresses are still considered "global unicast". if ip.Is4() && (ip == IPv4Unspecified() || ip == AddrFrom4([4]byte{255, 255, 255, 255})) { @@ -617,6 +637,10 @@ func (ip Addr) IsGlobalUnicast() bool { // ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7. This is the // same as [net.IP.IsPrivate]. func (ip Addr) IsPrivate() bool { + if ip.Is4In6() { + ip = ip.Unmap() + } + // Match the stdlib's IsPrivate logic. if ip.Is4() { // RFC 1918 allocates 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 as diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go index 4307df38bf..ad0e754208 100644 --- a/src/net/netip/netip_test.go +++ b/src/net/netip/netip_test.go @@ -599,10 +599,13 @@ func TestIPProperties(t *testing.T) { ilm6 = mustIP("ff01::1") ilmZone6 = mustIP("ff01::1%eth0") - private4a = mustIP("10.0.0.1") - private4b = mustIP("172.16.0.1") - private4c = mustIP("192.168.1.1") - private6 = mustIP("fd00::1") + private4a = mustIP("10.0.0.1") + private4b = mustIP("172.16.0.1") + private4c = mustIP("192.168.1.1") + private6 = mustIP("fd00::1") + private6mapped4a = mustIP("::ffff:10.0.0.1") + private6mapped4b = mustIP("::ffff:172.16.0.1") + private6mapped4c = mustIP("::ffff:192.168.1.1") ) tests := []struct { @@ -626,6 +629,11 @@ func TestIPProperties(t *testing.T) { ip: unicast4, globalUnicast: true, }, + { + name: "unicast v6 mapped v4Addr", + ip: AddrFrom16(unicast4.As16()), + globalUnicast: true, + }, { name: "unicast v6Addr", ip: unicast6, @@ -647,6 +655,12 @@ func TestIPProperties(t *testing.T) { linkLocalMulticast: true, multicast: true, }, + { + name: "multicast v6 mapped v4Addr", + ip: AddrFrom16(multicast4.As16()), + linkLocalMulticast: true, + multicast: true, + }, { name: "multicast v6Addr", ip: multicast6, @@ -664,6 +678,11 @@ func TestIPProperties(t *testing.T) { ip: llu4, linkLocalUnicast: true, }, + { + name: "link-local unicast v6 mapped v4Addr", + ip: AddrFrom16(llu4.As16()), + linkLocalUnicast: true, + }, { name: "link-local unicast v6Addr", ip: llu6, @@ -689,6 +708,11 @@ func TestIPProperties(t *testing.T) { ip: IPv6Loopback(), loopback: true, }, + { + name: "loopback v6 mapped v4Addr", + ip: AddrFrom16(IPv6Loopback().As16()), + loopback: true, + }, { name: "interface-local multicast v6Addr", ip: ilm6, @@ -725,6 +749,24 @@ func TestIPProperties(t *testing.T) { globalUnicast: true, private: true, }, + { + name: "private v6 mapped v4Addr 10/8", + ip: private6mapped4a, + globalUnicast: true, + private: true, + }, + { + name: "private v6 mapped v4Addr 172.16/12", + ip: private6mapped4b, + globalUnicast: true, + private: true, + }, + { + name: "private v6 mapped v4Addr 192.168/16", + ip: private6mapped4c, + globalUnicast: true, + private: true, + }, { name: "unspecified v4Addr", ip: IPv4Unspecified(), -- 2.48.1