summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArchana Polampalli <archana.polampalli@windriver.com>2025-11-28 21:37:58 +0530
committerSteve Sakoman <steve@sakoman.com>2025-12-05 06:56:34 -0800
commit46c836aefa1968e2ea8bdbdcc1bff6d329ddcc24 (patch)
tree615760bc2a74ce0accc51eebb57e1f4b426186d1
parent5f8155aefa0930c0495f24cfc2dbecc8b6ff4e0d (diff)
downloadpoky-46c836aefa1968e2ea8bdbdcc1bff6d329ddcc24.tar.gz
go: fix CVE-2025-61723
The processing time for parsing some invalid inputs scales non-linearly with respect to the size of the input. This affects programs which parse untrusted PEM inputs. (From OE-Core rev: cfafebef95330e531ab7bb590e5fb566dd5a3dce) Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r--meta/recipes-devtools/go/go-1.17.13.inc1
-rw-r--r--meta/recipes-devtools/go/go-1.18/CVE-2025-61723.patch221
2 files changed, 222 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.17.13.inc b/meta/recipes-devtools/go/go-1.17.13.inc
index 61fee12cf9..b621fb189c 100644
--- a/meta/recipes-devtools/go/go-1.17.13.inc
+++ b/meta/recipes-devtools/go/go-1.17.13.inc
@@ -71,6 +71,7 @@ SRC_URI = "https://golang.org/dl/go${PV}.src.tar.gz;name=main \
71 file://CVE-2024-24783.patch \ 71 file://CVE-2024-24783.patch \
72 file://CVE-2025-58187.patch \ 72 file://CVE-2025-58187.patch \
73 file://CVE-2025-58189.patch \ 73 file://CVE-2025-58189.patch \
74 file://CVE-2025-61723.patch \
74 " 75 "
75SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd" 76SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd"
76 77
diff --git a/meta/recipes-devtools/go/go-1.18/CVE-2025-61723.patch b/meta/recipes-devtools/go/go-1.18/CVE-2025-61723.patch
new file mode 100644
index 0000000000..8c838a6d8a
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.18/CVE-2025-61723.patch
@@ -0,0 +1,221 @@
1From 74d4d836b91318a8764b94bc2b4b66ff599eb5f2 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Tue, 30 Sep 2025 11:16:56 -0700
4Subject: [PATCH] encoding/pem: make Decode complexity linear Because Decode
5 scanned the input first for the first BEGIN line, and then the first END
6 line, the complexity of Decode is quadratic. If the input contained a large
7 number of BEGINs and then a single END right at the end of the input, we
8 would find the first BEGIN, and then scan the entire input for the END, and
9 fail to parse the block, so move onto the next BEGIN, scan the entire input
10 for the END, etc.
11
12Instead, look for the first END in the input, and then the first BEGIN
13that precedes the found END. We then process the bytes between the BEGIN
14and END, and move onto the bytes after the END for further processing.
15This gives us linear complexity.
16
17Fixes CVE-2025-61723
18For #75676
19Fixes #75708
20
21Change-Id: I813c4f63e78bca4054226c53e13865c781564ccf
22Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2921
23Reviewed-by: Nicholas Husin <husin@google.com>
24Reviewed-by: Damien Neil <dneil@google.com>
25Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2986
26Reviewed-on: https://go-review.googlesource.com/c/go/+/709842
27TryBot-Bypass: Michael Pratt <mpratt@google.com>
28Auto-Submit: Michael Pratt <mpratt@google.com>
29Reviewed-by: Carlos Amedee <carlos@golang.org>
30
31CVE: CVE-2025-61723
32
33Upstream-Status: Backport [https://github.com/golang/go/commit/74d4d836b91318a8764b94bc2b4b66ff599eb5f2]
34
35Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
36---
37 src/encoding/pem/pem.go | 67 +++++++++++++++++++-----------------
38 src/encoding/pem/pem_test.go | 13 +++----
39 2 files changed, 43 insertions(+), 37 deletions(-)
40
41diff --git a/src/encoding/pem/pem.go b/src/encoding/pem/pem.go
42index 1bee1c1..01bed75 100644
43--- a/src/encoding/pem/pem.go
44+++ b/src/encoding/pem/pem.go
45@@ -35,7 +35,7 @@ type Block struct {
46 // line bytes. The remainder of the byte array (also not including the new line
47 // bytes) is also returned and this will always be smaller than the original
48 // argument.
49-func getLine(data []byte) (line, rest []byte) {
50+func getLine(data []byte) (line, rest []byte, consumed int) {
51 i := bytes.IndexByte(data, '\n')
52 var j int
53 if i < 0 {
54@@ -47,7 +47,7 @@ func getLine(data []byte) (line, rest []byte) {
55 i--
56 }
57 }
58- return bytes.TrimRight(data[0:i], " \t"), data[j:]
59+ return bytes.TrimRight(data[0:i], " \t"), data[j:], j
60 }
61
62 // removeSpacesAndTabs returns a copy of its input with all spaces and tabs
63@@ -88,19 +88,29 @@ func Decode(data []byte) (p *Block, rest []byte) {
64 // the byte array, we'll accept the start string without it.
65 rest = data
66 for {
67- if bytes.HasPrefix(rest, pemStart[1:]) {
68- rest = rest[len(pemStart)-1:]
69- } else if i := bytes.Index(rest, pemStart); i >= 0 {
70- rest = rest[i+len(pemStart) : len(rest)]
71- } else {
72+ // Find the first END line, and then find the last BEGIN line before
73+ // the end line. This lets us skip any repeated BEGIN lines that don't
74+ // have a matching END.
75+ endIndex := bytes.Index(rest, pemEnd)
76+ if endIndex < 0 {
77 return nil, data
78 }
79-
80+ endTrailerIndex := endIndex + len(pemEnd)
81+ beginIndex := bytes.LastIndex(rest[:endIndex], pemStart[1:])
82+ if beginIndex < 0 || beginIndex > 0 && rest[beginIndex-1] != '\n' {
83+ return nil, data
84+ }
85+ rest = rest[beginIndex+len(pemStart)-1:]
86+ endIndex -= beginIndex + len(pemStart) - 1
87+ endTrailerIndex -= beginIndex + len(pemStart) - 1
88 var typeLine []byte
89- typeLine, rest = getLine(rest)
90+ var consumed int
91+ typeLine, rest, consumed = getLine(rest)
92 if !bytes.HasSuffix(typeLine, pemEndOfLine) {
93 continue
94 }
95+ endIndex -= consumed
96+ endTrailerIndex -= consumed
97 typeLine = typeLine[0 : len(typeLine)-len(pemEndOfLine)]
98
99 p = &Block{
100@@ -114,7 +124,7 @@ func Decode(data []byte) (p *Block, rest []byte) {
101 if len(rest) == 0 {
102 return nil, data
103 }
104- line, next := getLine(rest)
105+ line, next, consumed := getLine(rest)
106
107 i := bytes.IndexByte(line, ':')
108 if i == -1 {
109@@ -127,21 +137,13 @@ func Decode(data []byte) (p *Block, rest []byte) {
110 val = bytes.TrimSpace(val)
111 p.Headers[string(key)] = string(val)
112 rest = next
113+ endIndex -= consumed
114+ endTrailerIndex -= consumed
115 }
116
117- var endIndex, endTrailerIndex int
118-
119- // If there were no headers, the END line might occur
120- // immediately, without a leading newline.
121- if len(p.Headers) == 0 && bytes.HasPrefix(rest, pemEnd[1:]) {
122- endIndex = 0
123- endTrailerIndex = len(pemEnd) - 1
124- } else {
125- endIndex = bytes.Index(rest, pemEnd)
126- endTrailerIndex = endIndex + len(pemEnd)
127- }
128-
129- if endIndex < 0 {
130+ // If there were headers, there must be a newline between the headers
131+ // and the END line, so endIndex should be >= 0.
132+ if len(p.Headers) > 0 && endIndex < 0 {
133 continue
134 }
135
136@@ -161,21 +163,24 @@ func Decode(data []byte) (p *Block, rest []byte) {
137 }
138
139 // The line must end with only whitespace.
140- if s, _ := getLine(restOfEndLine); len(s) != 0 {
141+ if s, _, _ := getLine(restOfEndLine); len(s) != 0 {
142 continue
143 }
144
145- base64Data := removeSpacesAndTabs(rest[:endIndex])
146- p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data)))
147- n, err := base64.StdEncoding.Decode(p.Bytes, base64Data)
148- if err != nil {
149- continue
150+ p.Bytes = []byte{}
151+ if endIndex > 0 {
152+ base64Data := removeSpacesAndTabs(rest[:endIndex])
153+ p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data)))
154+ n, err := base64.StdEncoding.Decode(p.Bytes, base64Data)
155+ if err != nil {
156+ continue
157+ }
158+ p.Bytes = p.Bytes[:n]
159 }
160- p.Bytes = p.Bytes[:n]
161
162 // the -1 is because we might have only matched pemEnd without the
163 // leading newline if the PEM block was empty.
164- _, rest = getLine(rest[endIndex+len(pemEnd)-1:])
165+ _, rest, _ = getLine(rest[endIndex+len(pemEnd)-1:])
166 return p, rest
167 }
168 }
169diff --git a/src/encoding/pem/pem_test.go b/src/encoding/pem/pem_test.go
170index c94b5ca..a326f9b 100644
171--- a/src/encoding/pem/pem_test.go
172+++ b/src/encoding/pem/pem_test.go
173@@ -34,7 +34,7 @@ var getLineTests = []GetLineTest{
174
175 func TestGetLine(t *testing.T) {
176 for i, test := range getLineTests {
177- x, y := getLine([]byte(test.in))
178+ x, y, _ := getLine([]byte(test.in))
179 if string(x) != test.out1 || string(y) != test.out2 {
180 t.Errorf("#%d got:%+v,%+v want:%s,%s", i, x, y, test.out1, test.out2)
181 }
182@@ -46,6 +46,7 @@ func TestDecode(t *testing.T) {
183 if !reflect.DeepEqual(result, certificate) {
184 t.Errorf("#0 got:%#v want:%#v", result, certificate)
185 }
186+
187 result, remainder = Decode(remainder)
188 if !reflect.DeepEqual(result, privateKey) {
189 t.Errorf("#1 got:%#v want:%#v", result, privateKey)
190@@ -68,7 +69,7 @@ func TestDecode(t *testing.T) {
191 }
192
193 result, remainder = Decode(remainder)
194- if result == nil || result.Type != "HEADERS" || len(result.Headers) != 1 {
195+ if result == nil || result.Type != "VALID HEADERS" || len(result.Headers) != 1 {
196 t.Errorf("#5 expected single header block but got :%v", result)
197 }
198
199@@ -381,15 +382,15 @@ ZWAaUoVtWIQ52aKS0p19G99hhb+IVANC4akkdHV4SP8i7MVNZhfUmg==
200
201 # This shouldn't be recognised because of the missing newline after the
202 headers.
203------BEGIN HEADERS-----
204+-----BEGIN INVALID HEADERS-----
205 Header: 1
206------END HEADERS-----
207+-----END INVALID HEADERS-----
208
209 # This should be valid, however.
210------BEGIN HEADERS-----
211+-----BEGIN VALID HEADERS-----
212 Header: 1
213
214------END HEADERS-----`)
215+-----END VALID HEADERS-----`)
216
217 var certificate = &Block{Type: "CERTIFICATE",
218 Headers: map[string]string{},
219--
2202.40.0
221