summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/go/go-1.14/CVE-2023-45290.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/go/go-1.14/CVE-2023-45290.patch')
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-45290.patch271
1 files changed, 271 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-45290.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-45290.patch
new file mode 100644
index 0000000000..ddc2f67c96
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-45290.patch
@@ -0,0 +1,271 @@
1From bf80213b121074f4ad9b449410a4d13bae5e9be0 Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Tue, 16 Jan 2024 15:37:52 -0800
4Subject: [PATCH] [release-branch.go1.21] net/textproto, mime/multipart: avoid
5 unbounded read in MIME header
6
7mime/multipart.Reader.ReadForm allows specifying the maximum amount
8of memory that will be consumed by the form. While this limit is
9correctly applied to the parsed form data structure, it was not
10being applied to individual header lines in a form.
11
12For example, when presented with a form containing a header line
13that never ends, ReadForm will continue to read the line until it
14runs out of memory.
15
16Limit the amount of data consumed when reading a header.
17
18Fixes CVE-2023-45290
19Fixes #65389
20For #65383
21
22Change-Id: I7f9264d25752009e95f6b2c80e3d76aaf321d658
23Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2134435
24Reviewed-by: Roland Shoemaker <bracewell@google.com>
25Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
26Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173776
27Reviewed-by: Carlos Amedee <amedee@google.com>
28Reviewed-on: https://go-review.googlesource.com/c/go/+/569240
29Auto-Submit: Michael Knyszek <mknyszek@google.com>
30LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
31Reviewed-by: Carlos Amedee <carlos@golang.org>
32
33Upstream-Status: Backport [https://github.com/golang/go/commit/bf80213b121074f4ad9b449410a4d13bae5e9be0]
34CVE: CVE-2023-45290
35Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
36---
37 src/mime/multipart/formdata_test.go | 42 +++++++++++++++++++++++++
38 src/net/textproto/reader.go | 48 ++++++++++++++++++++---------
39 src/net/textproto/reader_test.go | 12 ++++++++
40 3 files changed, 87 insertions(+), 15 deletions(-)
41
42diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
43index c78eeb7..f729da6 100644
44--- a/src/mime/multipart/formdata_test.go
45+++ b/src/mime/multipart/formdata_test.go
46@@ -421,6 +421,48 @@ func TestReadFormLimits(t *testing.T) {
47 }
48 }
49
50+func TestReadFormEndlessHeaderLine(t *testing.T) {
51+ for _, test := range []struct {
52+ name string
53+ prefix string
54+ }{{
55+ name: "name",
56+ prefix: "X-",
57+ }, {
58+ name: "value",
59+ prefix: "X-Header: ",
60+ }, {
61+ name: "continuation",
62+ prefix: "X-Header: foo\r\n ",
63+ }} {
64+ t.Run(test.name, func(t *testing.T) {
65+ const eol = "\r\n"
66+ s := `--boundary` + eol
67+ s += `Content-Disposition: form-data; name="a"` + eol
68+ s += `Content-Type: text/plain` + eol
69+ s += test.prefix
70+ fr := io.MultiReader(
71+ strings.NewReader(s),
72+ neverendingReader('X'),
73+ )
74+ r := NewReader(fr, "boundary")
75+ _, err := r.ReadForm(1 << 20)
76+ if err != ErrMessageTooLarge {
77+ t.Fatalf("ReadForm(1 << 20): %v, want ErrMessageTooLarge", err)
78+ }
79+ })
80+ }
81+}
82+
83+type neverendingReader byte
84+
85+func (r neverendingReader) Read(p []byte) (n int, err error) {
86+ for i := range p {
87+ p[i] = byte(r)
88+ }
89+ return len(p), nil
90+}
91+
92 func BenchmarkReadForm(b *testing.B) {
93 for _, test := range []struct {
94 name string
95diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
96index ad2d777..cea6613 100644
97--- a/src/net/textproto/reader.go
98+++ b/src/net/textproto/reader.go
99@@ -17,6 +17,10 @@ import (
100 "sync"
101 )
102
103+// TODO: This should be a distinguishable error (ErrMessageTooLarge)
104+// to allow mime/multipart to detect it.
105+var errMessageTooLarge = errors.New("message too large")
106+
107 // A Reader implements convenience methods for reading requests
108 // or responses from a text protocol network connection.
109 type Reader struct {
110@@ -38,13 +42,13 @@ func NewReader(r *bufio.Reader) *Reader {
111 // ReadLine reads a single line from r,
112 // eliding the final \n or \r\n from the returned string.
113 func (r *Reader) ReadLine() (string, error) {
114- line, err := r.readLineSlice()
115+ line, err := r.readLineSlice(-1)
116 return string(line), err
117 }
118
119 // ReadLineBytes is like ReadLine but returns a []byte instead of a string.
120 func (r *Reader) ReadLineBytes() ([]byte, error) {
121- line, err := r.readLineSlice()
122+ line, err := r.readLineSlice(-1)
123 if line != nil {
124 buf := make([]byte, len(line))
125 copy(buf, line)
126@@ -53,7 +57,10 @@ func (r *Reader) ReadLineBytes() ([]byte, error) {
127 return line, err
128 }
129
130-func (r *Reader) readLineSlice() ([]byte, error) {
131+// readLineSlice reads a single line from r,
132+// up to lim bytes long (or unlimited if lim is less than 0),
133+// eliding the final \r or \r\n from the returned string.
134+func (r *Reader) readLineSlice(lim int64) ([]byte, error) {
135 r.closeDot()
136 var line []byte
137 for {
138@@ -61,6 +68,9 @@ func (r *Reader) readLineSlice() ([]byte, error) {
139 if err != nil {
140 return nil, err
141 }
142+ if lim >= 0 && int64(len(line))+int64(len(l)) > lim {
143+ return nil, errMessageTooLarge
144+ }
145 // Avoid the copy if the first call produced a full line.
146 if line == nil && !more {
147 return l, nil
148@@ -93,7 +103,7 @@ func (r *Reader) readLineSlice() ([]byte, error) {
149 // A line consisting of only white space is never continued.
150 //
151 func (r *Reader) ReadContinuedLine() (string, error) {
152- line, err := r.readContinuedLineSlice(noValidation)
153+ line, err := r.readContinuedLineSlice(-1, noValidation)
154 return string(line), err
155 }
156
157@@ -114,7 +124,7 @@ func trim(s []byte) []byte {
158 // ReadContinuedLineBytes is like ReadContinuedLine but
159 // returns a []byte instead of a string.
160 func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
161- line, err := r.readContinuedLineSlice(noValidation)
162+ line, err := r.readContinuedLineSlice(-1, noValidation)
163 if line != nil {
164 buf := make([]byte, len(line))
165 copy(buf, line)
166@@ -127,13 +137,14 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
167 // returning a byte slice with all lines. The validateFirstLine function
168 // is run on the first read line, and if it returns an error then this
169 // error is returned from readContinuedLineSlice.
170-func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([]byte, error) {
171+// It reads up to lim bytes of data (or unlimited if lim is less than 0).
172+func (r *Reader) readContinuedLineSlice(lim int64, validateFirstLine func([]byte) error) ([]byte, error) {
173 if validateFirstLine == nil {
174 return nil, fmt.Errorf("missing validateFirstLine func")
175 }
176
177 // Read the first line.
178- line, err := r.readLineSlice()
179+ line, err := r.readLineSlice(lim)
180 if err != nil {
181 return nil, err
182 }
183@@ -161,13 +172,21 @@ func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([
184 // copy the slice into buf.
185 r.buf = append(r.buf[:0], trim(line)...)
186
187+ if lim < 0 {
188+ lim = math.MaxInt64
189+ }
190+ lim -= int64(len(r.buf))
191+
192 // Read continuation lines.
193 for r.skipSpace() > 0 {
194- line, err := r.readLineSlice()
195+ r.buf = append(r.buf, ' ')
196+ if int64(len(r.buf)) >= lim {
197+ return nil, errMessageTooLarge
198+ }
199+ line, err := r.readLineSlice(lim - int64(len(r.buf)))
200 if err != nil {
201 break
202 }
203- r.buf = append(r.buf, ' ')
204 r.buf = append(r.buf, trim(line)...)
205 }
206 return r.buf, nil
207@@ -512,7 +531,8 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
208
209 // The first line cannot start with a leading space.
210 if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') {
211- line, err := r.readLineSlice()
212+ const errorLimit = 80 // arbitrary limit on how much of the line we'll quote
213+ line, err := r.readLineSlice(errorLimit)
214 if err != nil {
215 return m, err
216 }
217@@ -520,7 +540,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
218 }
219
220 for {
221- kv, err := r.readContinuedLineSlice(mustHaveFieldNameColon)
222+ kv, err := r.readContinuedLineSlice(maxMemory, mustHaveFieldNameColon)
223 if len(kv) == 0 {
224 return m, err
225 }
226@@ -541,7 +561,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
227
228 maxHeaders--
229 if maxHeaders < 0 {
230- return nil, errors.New("message too large")
231+ return nil, errMessageTooLarge
232 }
233
234 // backport 5c55ac9bf1e5f779220294c843526536605f42ab
235@@ -567,9 +587,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
236 }
237 maxMemory -= int64(len(value))
238 if maxMemory < 0 {
239- // TODO: This should be a distinguishable error (ErrMessageTooLarge)
240- // to allow mime/multipart to detect it.
241- return m, errors.New("message too large")
242+ return m, errMessageTooLarge
243 }
244 if vv == nil && len(strs) > 0 {
245 // More than likely this will be a single-element key.
246diff --git a/src/net/textproto/reader_test.go b/src/net/textproto/reader_test.go
247index 3ae0de1..db1ed91 100644
248--- a/src/net/textproto/reader_test.go
249+++ b/src/net/textproto/reader_test.go
250@@ -34,6 +34,18 @@ func TestReadLine(t *testing.T) {
251 }
252 }
253
254+func TestReadLineLongLine(t *testing.T) {
255+ line := strings.Repeat("12345", 10000)
256+ r := reader(line + "\r\n")
257+ s, err := r.ReadLine()
258+ if err != nil {
259+ t.Fatalf("Line 1: %v", err)
260+ }
261+ if s != line {
262+ t.Fatalf("%v-byte line does not match expected %v-byte line", len(s), len(line))
263+ }
264+}
265+
266 func TestReadContinuedLine(t *testing.T) {
267 r := reader("line1\nline\n 2\nline3\n")
268 s, err := r.ReadContinuedLine()
269--
2702.25.1
271