summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVijay Anusuri <vanusuri@mvista.com>2025-12-29 21:14:01 +0530
committerSteve Sakoman <steve@sakoman.com>2026-01-02 06:56:54 -0800
commit795103a538c5086f5f0dfcfd9c20e57f1e513811 (patch)
treea748c7a0ef2011b4e6e1f03575c93d87deb3e3a4
parentd3c87dc830a9ca59ca0fb8b646c2983d484bfcd1 (diff)
downloadpoky-795103a538c5086f5f0dfcfd9c20e57f1e513811.tar.gz
go: Fix CVE-2025-61729
Upstream-Status: Backport from https://github.com/golang/go/commit/3a842bd5c6aa8eefa13c0174de3ab361e50bd672 (From OE-Core rev: 2d6d68e46a430a1dbba7bd8b7d37ff56f4f5a0e6) Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r--meta/recipes-devtools/go/go-1.22.12.inc1
-rw-r--r--meta/recipes-devtools/go/go/CVE-2025-61729.patch174
2 files changed, 175 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.22.12.inc b/meta/recipes-devtools/go/go-1.22.12.inc
index 664ccf3edc..ca5016c2f5 100644
--- a/meta/recipes-devtools/go/go-1.22.12.inc
+++ b/meta/recipes-devtools/go/go-1.22.12.inc
@@ -30,6 +30,7 @@ SRC_URI += "\
30 file://CVE-2025-61723.patch \ 30 file://CVE-2025-61723.patch \
31 file://CVE-2025-61724.patch \ 31 file://CVE-2025-61724.patch \
32 file://CVE-2025-61727.patch \ 32 file://CVE-2025-61727.patch \
33 file://CVE-2025-61729.patch \
33" 34"
34SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71" 35SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71"
35 36
diff --git a/meta/recipes-devtools/go/go/CVE-2025-61729.patch b/meta/recipes-devtools/go/go/CVE-2025-61729.patch
new file mode 100644
index 0000000000..08859e5729
--- /dev/null
+++ b/meta/recipes-devtools/go/go/CVE-2025-61729.patch
@@ -0,0 +1,174 @@
1From 3a842bd5c6aa8eefa13c0174de3ab361e50bd672 Mon Sep 17 00:00:00 2001
2From: "Nicholas S. Husin" <nsh@golang.org>
3Date: Mon, 24 Nov 2025 14:56:23 -0500
4Subject: [PATCH] [release-branch.go1.24] crypto/x509: prevent
5 HostnameError.Error() from consuming excessive resource
6
7Constructing HostnameError.Error() takes O(N^2) runtime due to using a
8string concatenation in a loop. Additionally, there is no limit on how
9many names are included in the error message. As a result, a malicious
10attacker could craft a certificate with an infinite amount of names to
11unfairly consume resource.
12
13To remediate this, we will now use strings.Builder to construct the
14error message, preventing O(N^2) runtime. When a certificate has 100 or
15more names, we will also not print each name individually.
16
17Thanks to Philippe Antoine (Catena cyber) for reporting this issue.
18
19Updates #76445
20Fixes #76460
21Fixes CVE-2025-61729
22
23Change-Id: I6343776ec3289577abc76dad71766c491c1a7c81
24Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3000
25Reviewed-by: Neal Patel <nealpatel@google.com>
26Reviewed-by: Damien Neil <dneil@google.com>
27Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3220
28Reviewed-by: Roland Shoemaker <bracewell@google.com>
29Reviewed-on: https://go-review.googlesource.com/c/go/+/725820
30Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
31TryBot-Bypass: Dmitri Shuralyov <dmitshur@golang.org>
32Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
33Reviewed-by: Mark Freeman <markfreeman@google.com>
34
35Upstream-Status: Backport [https://github.com/golang/go/commit/3a842bd5c6aa8eefa13c0174de3ab361e50bd672]
36CVE: CVE-2025-61729
37Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
38---
39 src/crypto/x509/verify.go | 21 ++++++++++-----
40 src/crypto/x509/verify_test.go | 47 ++++++++++++++++++++++++++++++++++
41 2 files changed, 61 insertions(+), 7 deletions(-)
42
43diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
44index 3fdf65f..0ae8aef 100644
45--- a/src/crypto/x509/verify.go
46+++ b/src/crypto/x509/verify.go
47@@ -100,31 +100,38 @@ type HostnameError struct {
48
49 func (h HostnameError) Error() string {
50 c := h.Certificate
51+ maxNamesIncluded := 100
52
53 if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, h.Host) {
54 return "x509: certificate relies on legacy Common Name field, use SANs instead"
55 }
56
57- var valid string
58+ var valid strings.Builder
59 if ip := net.ParseIP(h.Host); ip != nil {
60 // Trying to validate an IP
61 if len(c.IPAddresses) == 0 {
62 return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
63 }
64+ if len(c.IPAddresses) >= maxNamesIncluded {
65+ return fmt.Sprintf("x509: certificate is valid for %d IP SANs, but none matched %s", len(c.IPAddresses), h.Host)
66+ }
67 for _, san := range c.IPAddresses {
68- if len(valid) > 0 {
69- valid += ", "
70+ if valid.Len() > 0 {
71+ valid.WriteString(", ")
72 }
73- valid += san.String()
74+ valid.WriteString(san.String())
75 }
76 } else {
77- valid = strings.Join(c.DNSNames, ", ")
78+ if len(c.DNSNames) >= maxNamesIncluded {
79+ return fmt.Sprintf("x509: certificate is valid for %d names, but none matched %s", len(c.DNSNames), h.Host)
80+ }
81+ valid.WriteString(strings.Join(c.DNSNames, ", "))
82 }
83
84- if len(valid) == 0 {
85+ if valid.Len() == 0 {
86 return "x509: certificate is not valid for any names, but wanted to match " + h.Host
87 }
88- return "x509: certificate is valid for " + valid + ", not " + h.Host
89+ return "x509: certificate is valid for " + valid.String() + ", not " + h.Host
90 }
91
92 // UnknownAuthorityError results when the certificate issuer is unknown
93diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go
94index df9b0a2..223c250 100644
95--- a/src/crypto/x509/verify_test.go
96+++ b/src/crypto/x509/verify_test.go
97@@ -10,13 +10,16 @@ import (
98 "crypto/ecdsa"
99 "crypto/elliptic"
100 "crypto/rand"
101+ "crypto/rsa"
102 "crypto/x509/pkix"
103 "encoding/asn1"
104 "encoding/pem"
105 "errors"
106 "fmt"
107 "internal/testenv"
108+ "log"
109 "math/big"
110+ "net"
111 "os/exec"
112 "reflect"
113 "runtime"
114@@ -89,6 +92,26 @@ var verifyTests = []verifyTest{
115
116 errorCallback: expectHostnameError("certificate is valid for"),
117 },
118+ {
119+ name: "TooManyDNS",
120+ leaf: generatePEMCertWithRepeatSAN(1677615892, 200, "fake.dns"),
121+ roots: []string{generatePEMCertWithRepeatSAN(1677615892, 200, "fake.dns")},
122+ currentTime: 1677615892,
123+ dnsName: "www.example.com",
124+ systemSkip: true, // does not chain to a system root
125+
126+ errorCallback: expectHostnameError("certificate is valid for 200 names, but none matched"),
127+ },
128+ {
129+ name: "TooManyIPs",
130+ leaf: generatePEMCertWithRepeatSAN(1677615892, 150, "4.3.2.1"),
131+ roots: []string{generatePEMCertWithRepeatSAN(1677615892, 150, "4.3.2.1")},
132+ currentTime: 1677615892,
133+ dnsName: "1.2.3.4",
134+ systemSkip: true, // does not chain to a system root
135+
136+ errorCallback: expectHostnameError("certificate is valid for 150 IP SANs, but none matched"),
137+ },
138 {
139 name: "IPMissing",
140 leaf: googleLeaf,
141@@ -595,6 +618,30 @@ func nameToKey(name *pkix.Name) string {
142 return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
143 }
144
145+func generatePEMCertWithRepeatSAN(currentTime int64, count int, san string) string {
146+ cert := Certificate{
147+ NotBefore: time.Unix(currentTime, 0),
148+ NotAfter: time.Unix(currentTime, 0),
149+ }
150+ if ip := net.ParseIP(san); ip != nil {
151+ cert.IPAddresses = slices.Repeat([]net.IP{ip}, count)
152+ } else {
153+ cert.DNSNames = slices.Repeat([]string{san}, count)
154+ }
155+ privKey, err := rsa.GenerateKey(rand.Reader, 4096)
156+ if err != nil {
157+ log.Fatal(err)
158+ }
159+ certBytes, err := CreateCertificate(rand.Reader, &cert, &cert, &privKey.PublicKey, privKey)
160+ if err != nil {
161+ log.Fatal(err)
162+ }
163+ return string(pem.EncodeToMemory(&pem.Block{
164+ Type: "CERTIFICATE",
165+ Bytes: certBytes,
166+ }))
167+}
168+
169 const gtsIntermediate = `-----BEGIN CERTIFICATE-----
170 MIIFljCCA36gAwIBAgINAgO8U1lrNMcY9QFQZjANBgkqhkiG9w0BAQsFADBHMQsw
171 CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
172--
1732.43.0
174