summaryrefslogtreecommitdiff
path: root/backport-0008-release-branch.go1.21-net-netip-check-if-address-is-v6.patch
blob: 261dbe02f2559fd4471dcbd66b6145aac482d504 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
From 051bdf3fd12a40307606ff9381138039c5f452f0 Mon Sep 17 00:00:00 2001
From: Roland Shoemaker <bracewell@google.com>
Date: Tue, 28 May 2024 13:26:31 -0700
Subject: [PATCH] [release-branch.go1.21] 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 #67681
Fixes CVE-2024-24790

Change-Id: I6bd03ca1a5d93a0b59027d861c84060967b265b0
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1460
Reviewed-by: Russ Cox <rsc@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
(cherry picked from commit f7f270c1621fdc7ee48e0487b2fac0356947d19b)
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1500
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/590315
Auto-Submit: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
---
 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 b521eeebfd8f3..98584b098df1b 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 a44b09495549d..9e4d41f8fb7b9 100644
--- a/src/net/netip/netip.go
+++ b/src/net/netip/netip.go
@@ -507,6 +507,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() {
@@ -522,6 +526,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() {
@@ -537,6 +545,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() {
@@ -555,7 +567,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
@@ -563,6 +575,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() {
@@ -591,6 +607,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})) {
@@ -608,6 +628,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 0f80bb0ab0e56..5c7ad14c5c702 100644
--- a/src/net/netip/netip_test.go
+++ b/src/net/netip/netip_test.go
@@ -589,10 +589,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 {
@@ -616,6 +619,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,
@@ -637,6 +645,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,
@@ -654,6 +668,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,
@@ -679,6 +698,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,
@@ -715,6 +739,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(),