xref: /OK3568_Linux_fs/yocto/poky/meta/recipes-devtools/go/go-1.18/CVE-2022-2879.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593SmuzhiyunFrom d064ed520a7cc6b480f9565e30751e695d394f4e Mon Sep 17 00:00:00 2001
2*4882a593SmuzhiyunFrom: Damien Neil <dneil@google.com>
3*4882a593SmuzhiyunDate: Fri, 2 Sep 2022 20:45:18 -0700
4*4882a593SmuzhiyunSubject: [PATCH] archive/tar: limit size of headers
5*4882a593Smuzhiyun
6*4882a593SmuzhiyunSet a 1MiB limit on special file blocks (PAX headers, GNU long names,
7*4882a593SmuzhiyunGNU link names), to avoid reading arbitrarily large amounts of data
8*4882a593Smuzhiyuninto memory.
9*4882a593Smuzhiyun
10*4882a593SmuzhiyunThanks to Adam Korczynski (ADA Logics) and OSS-Fuzz for reporting
11*4882a593Smuzhiyunthis issue.
12*4882a593Smuzhiyun
13*4882a593SmuzhiyunFixes CVE-2022-2879
14*4882a593SmuzhiyunUpdates #54853
15*4882a593SmuzhiyunFixes #55925
16*4882a593Smuzhiyun
17*4882a593SmuzhiyunChange-Id: I85136d6ff1e0af101a112190e027987ab4335680
18*4882a593SmuzhiyunReviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1565555
19*4882a593SmuzhiyunReviewed-by: Tatiana Bradley <tatianabradley@google.com>
20*4882a593SmuzhiyunRun-TryBot: Roland Shoemaker <bracewell@google.com>
21*4882a593SmuzhiyunReviewed-by: Roland Shoemaker <bracewell@google.com>
22*4882a593Smuzhiyun(cherry picked from commit 6ee768cef6b82adf7a90dcf367a1699ef694f3b2)
23*4882a593SmuzhiyunReviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1590622
24*4882a593SmuzhiyunReviewed-by: Damien Neil <dneil@google.com>
25*4882a593SmuzhiyunReviewed-by: Julie Qiu <julieqiu@google.com>
26*4882a593SmuzhiyunReviewed-on: https://go-review.googlesource.com/c/go/+/438500
27*4882a593SmuzhiyunReviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
28*4882a593SmuzhiyunReviewed-by: Carlos Amedee <carlos@golang.org>
29*4882a593SmuzhiyunReviewed-by: Dmitri Shuralyov <dmitshur@google.com>
30*4882a593SmuzhiyunRun-TryBot: Carlos Amedee <carlos@golang.org>
31*4882a593SmuzhiyunTryBot-Result: Gopher Robot <gobot@golang.org>
32*4882a593Smuzhiyun
33*4882a593SmuzhiyunCVE: CVE-2022-2879
34*4882a593SmuzhiyunUpstream-Status: Backport [0a723816cd205576945fa57fbdde7e6532d59d08]
35*4882a593SmuzhiyunSigned-off-by: Sakib Sajal <sakib.sajal@windriver.com>
36*4882a593Smuzhiyun---
37*4882a593Smuzhiyun src/archive/tar/format.go      |  4 ++++
38*4882a593Smuzhiyun src/archive/tar/reader.go      | 14 ++++++++++++--
39*4882a593Smuzhiyun src/archive/tar/reader_test.go |  8 +++++++-
40*4882a593Smuzhiyun src/archive/tar/writer.go      |  3 +++
41*4882a593Smuzhiyun src/archive/tar/writer_test.go | 27 +++++++++++++++++++++++++++
42*4882a593Smuzhiyun 5 files changed, 53 insertions(+), 3 deletions(-)
43*4882a593Smuzhiyun
44*4882a593Smuzhiyundiff --git a/src/archive/tar/format.go b/src/archive/tar/format.go
45*4882a593Smuzhiyunindex cfe24a5..6642364 100644
46*4882a593Smuzhiyun--- a/src/archive/tar/format.go
47*4882a593Smuzhiyun+++ b/src/archive/tar/format.go
48*4882a593Smuzhiyun@@ -143,6 +143,10 @@ const (
49*4882a593Smuzhiyun 	blockSize  = 512 // Size of each block in a tar stream
50*4882a593Smuzhiyun 	nameSize   = 100 // Max length of the name field in USTAR format
51*4882a593Smuzhiyun 	prefixSize = 155 // Max length of the prefix field in USTAR format
52*4882a593Smuzhiyun+
53*4882a593Smuzhiyun+	// Max length of a special file (PAX header, GNU long name or link).
54*4882a593Smuzhiyun+	// This matches the limit used by libarchive.
55*4882a593Smuzhiyun+	maxSpecialFileSize = 1 << 20
56*4882a593Smuzhiyun )
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun // blockPadding computes the number of bytes needed to pad offset up to the
59*4882a593Smuzhiyundiff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go
60*4882a593Smuzhiyunindex 1b1d5b4..f645af8 100644
61*4882a593Smuzhiyun--- a/src/archive/tar/reader.go
62*4882a593Smuzhiyun+++ b/src/archive/tar/reader.go
63*4882a593Smuzhiyun@@ -103,7 +103,7 @@ func (tr *Reader) next() (*Header, error) {
64*4882a593Smuzhiyun 			continue // This is a meta header affecting the next header
65*4882a593Smuzhiyun 		case TypeGNULongName, TypeGNULongLink:
66*4882a593Smuzhiyun 			format.mayOnlyBe(FormatGNU)
67*4882a593Smuzhiyun-			realname, err := io.ReadAll(tr)
68*4882a593Smuzhiyun+			realname, err := readSpecialFile(tr)
69*4882a593Smuzhiyun 			if err != nil {
70*4882a593Smuzhiyun 				return nil, err
71*4882a593Smuzhiyun 			}
72*4882a593Smuzhiyun@@ -293,7 +293,7 @@ func mergePAX(hdr *Header, paxHdrs map[string]string) (err error) {
73*4882a593Smuzhiyun // parsePAX parses PAX headers.
74*4882a593Smuzhiyun // If an extended header (type 'x') is invalid, ErrHeader is returned
75*4882a593Smuzhiyun func parsePAX(r io.Reader) (map[string]string, error) {
76*4882a593Smuzhiyun-	buf, err := io.ReadAll(r)
77*4882a593Smuzhiyun+	buf, err := readSpecialFile(r)
78*4882a593Smuzhiyun 	if err != nil {
79*4882a593Smuzhiyun 		return nil, err
80*4882a593Smuzhiyun 	}
81*4882a593Smuzhiyun@@ -826,6 +826,16 @@ func tryReadFull(r io.Reader, b []byte) (n int, err error) {
82*4882a593Smuzhiyun 	return n, err
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun+// readSpecialFile is like io.ReadAll except it returns
86*4882a593Smuzhiyun+// ErrFieldTooLong if more than maxSpecialFileSize is read.
87*4882a593Smuzhiyun+func readSpecialFile(r io.Reader) ([]byte, error) {
88*4882a593Smuzhiyun+	buf, err := io.ReadAll(io.LimitReader(r, maxSpecialFileSize+1))
89*4882a593Smuzhiyun+	if len(buf) > maxSpecialFileSize {
90*4882a593Smuzhiyun+		return nil, ErrFieldTooLong
91*4882a593Smuzhiyun+	}
92*4882a593Smuzhiyun+	return buf, err
93*4882a593Smuzhiyun+}
94*4882a593Smuzhiyun+
95*4882a593Smuzhiyun // discard skips n bytes in r, reporting an error if unable to do so.
96*4882a593Smuzhiyun func discard(r io.Reader, n int64) error {
97*4882a593Smuzhiyun 	// If possible, Seek to the last byte before the end of the data section.
98*4882a593Smuzhiyundiff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go
99*4882a593Smuzhiyunindex 789ddc1..926dc3d 100644
100*4882a593Smuzhiyun--- a/src/archive/tar/reader_test.go
101*4882a593Smuzhiyun+++ b/src/archive/tar/reader_test.go
102*4882a593Smuzhiyun@@ -6,6 +6,7 @@ package tar
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun import (
105*4882a593Smuzhiyun 	"bytes"
106*4882a593Smuzhiyun+	"compress/bzip2"
107*4882a593Smuzhiyun 	"crypto/md5"
108*4882a593Smuzhiyun 	"errors"
109*4882a593Smuzhiyun 	"fmt"
110*4882a593Smuzhiyun@@ -625,9 +626,14 @@ func TestReader(t *testing.T) {
111*4882a593Smuzhiyun 			}
112*4882a593Smuzhiyun 			defer f.Close()
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun+			var fr io.Reader = f
115*4882a593Smuzhiyun+			if strings.HasSuffix(v.file, ".bz2") {
116*4882a593Smuzhiyun+				fr = bzip2.NewReader(fr)
117*4882a593Smuzhiyun+			}
118*4882a593Smuzhiyun+
119*4882a593Smuzhiyun 			// Capture all headers and checksums.
120*4882a593Smuzhiyun 			var (
121*4882a593Smuzhiyun-				tr      = NewReader(f)
122*4882a593Smuzhiyun+				tr      = NewReader(fr)
123*4882a593Smuzhiyun 				hdrs    []*Header
124*4882a593Smuzhiyun 				chksums []string
125*4882a593Smuzhiyun 				rdbuf   = make([]byte, 8)
126*4882a593Smuzhiyundiff --git a/src/archive/tar/writer.go b/src/archive/tar/writer.go
127*4882a593Smuzhiyunindex e80498d..893eac0 100644
128*4882a593Smuzhiyun--- a/src/archive/tar/writer.go
129*4882a593Smuzhiyun+++ b/src/archive/tar/writer.go
130*4882a593Smuzhiyun@@ -199,6 +199,9 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error {
131*4882a593Smuzhiyun 			flag = TypeXHeader
132*4882a593Smuzhiyun 		}
133*4882a593Smuzhiyun 		data := buf.String()
134*4882a593Smuzhiyun+		if len(data) > maxSpecialFileSize {
135*4882a593Smuzhiyun+			return ErrFieldTooLong
136*4882a593Smuzhiyun+		}
137*4882a593Smuzhiyun 		if err := tw.writeRawFile(name, data, flag, FormatPAX); err != nil || isGlobal {
138*4882a593Smuzhiyun 			return err // Global headers return here
139*4882a593Smuzhiyun 		}
140*4882a593Smuzhiyundiff --git a/src/archive/tar/writer_test.go b/src/archive/tar/writer_test.go
141*4882a593Smuzhiyunindex a00f02d..4e709e5 100644
142*4882a593Smuzhiyun--- a/src/archive/tar/writer_test.go
143*4882a593Smuzhiyun+++ b/src/archive/tar/writer_test.go
144*4882a593Smuzhiyun@@ -1006,6 +1006,33 @@ func TestIssue12594(t *testing.T) {
145*4882a593Smuzhiyun 	}
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun+func TestWriteLongHeader(t *testing.T) {
149*4882a593Smuzhiyun+	for _, test := range []struct {
150*4882a593Smuzhiyun+		name string
151*4882a593Smuzhiyun+		h    *Header
152*4882a593Smuzhiyun+	}{{
153*4882a593Smuzhiyun+		name: "name too long",
154*4882a593Smuzhiyun+		h:    &Header{Name: strings.Repeat("a", maxSpecialFileSize)},
155*4882a593Smuzhiyun+	}, {
156*4882a593Smuzhiyun+		name: "linkname too long",
157*4882a593Smuzhiyun+		h:    &Header{Linkname: strings.Repeat("a", maxSpecialFileSize)},
158*4882a593Smuzhiyun+	}, {
159*4882a593Smuzhiyun+		name: "uname too long",
160*4882a593Smuzhiyun+		h:    &Header{Uname: strings.Repeat("a", maxSpecialFileSize)},
161*4882a593Smuzhiyun+	}, {
162*4882a593Smuzhiyun+		name: "gname too long",
163*4882a593Smuzhiyun+		h:    &Header{Gname: strings.Repeat("a", maxSpecialFileSize)},
164*4882a593Smuzhiyun+	}, {
165*4882a593Smuzhiyun+		name: "PAX header too long",
166*4882a593Smuzhiyun+		h:    &Header{PAXRecords: map[string]string{"GOLANG.x": strings.Repeat("a", maxSpecialFileSize)}},
167*4882a593Smuzhiyun+	}} {
168*4882a593Smuzhiyun+		w := NewWriter(io.Discard)
169*4882a593Smuzhiyun+		if err := w.WriteHeader(test.h); err != ErrFieldTooLong {
170*4882a593Smuzhiyun+			t.Errorf("%v: w.WriteHeader() = %v, want ErrFieldTooLong", test.name, err)
171*4882a593Smuzhiyun+		}
172*4882a593Smuzhiyun+	}
173*4882a593Smuzhiyun+}
174*4882a593Smuzhiyun+
175*4882a593Smuzhiyun // testNonEmptyWriter wraps an io.Writer and ensures that
176*4882a593Smuzhiyun // Write is never called with an empty buffer.
177*4882a593Smuzhiyun type testNonEmptyWriter struct{ io.Writer }
178