-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
create patch from release-branch.go1.16
- Loading branch information
Showing
1 changed file
with
211 additions
and
0 deletions.
There are no files selected for viewing
211 changes: 211 additions & 0 deletions
211
projects/golang/go/1.16/patches/0015-go-1.16.15-eks-archive-tar-limit-size-of-head.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
From 191a24750e97adfe3ebbc30bd7f4279d255d138b Mon Sep 17 00:00:00 2001 | ||
From: Damien Neil <dneil@google.com> | ||
Date: Fri, 2 Sep 2022 20:45:18 -0700 | ||
Subject: [PATCH] [release-branch.go1.18] archive/tar: limit size of headers | ||
|
||
# AWS EKS | ||
Backported To: go-1.16.15-eks | ||
Backported On: Thur, 6 Oct 2022 | ||
Backported By: rcrozean@amazon.com | ||
Backported From: release-branch.go1.18 | ||
Source Commit: https://github.com/golang/go/commit/0a723816cd205576945fa57fbdde7e6532d59d082879 | ||
EKS Patch Source Commit: | ||
|
||
# Original Information | ||
|
||
Set a 1MiB limit on special file blocks (PAX headers, GNU long names, | ||
GNU link names), to avoid reading arbitrarily large amounts of data | ||
into memory. | ||
|
||
Thanks to Adam Korczynski (ADA Logics) and OSS-Fuzz for reporting | ||
this issue. | ||
|
||
Fixes CVE-2022-2879 | ||
Updates #54853 | ||
Fixes #55925 | ||
|
||
Change-Id: I85136d6ff1e0af101a112190e027987ab4335680 | ||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1565555 | ||
Reviewed-by: Tatiana Bradley <tatianabradley@google.com> | ||
Run-TryBot: Roland Shoemaker <bracewell@google.com> | ||
Reviewed-by: Roland Shoemaker <bracewell@google.com> | ||
(cherry picked from commit 6ee768cef6b82adf7a90dcf367a1699ef694f3b2) | ||
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1590622 | ||
Reviewed-by: Damien Neil <dneil@google.com> | ||
Reviewed-by: Julie Qiu <julieqiu@google.com> | ||
Reviewed-on: https://go-review.googlesource.com/c/go/+/438500 | ||
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org> | ||
Reviewed-by: Carlos Amedee <carlos@golang.org> | ||
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> | ||
Run-TryBot: Carlos Amedee <carlos@golang.org> | ||
TryBot-Result: Gopher Robot <gobot@golang.org> | ||
--- | ||
src/archive/tar/format.go | 4 +++ | ||
src/archive/tar/reader.go | 14 +++++++-- | ||
src/archive/tar/reader_test.go | 11 ++++++- | ||
.../tar/testdata/pax-bad-hdr-large.tar.bz2 | Bin 0 -> 156 bytes | ||
src/archive/tar/writer.go | 3 ++ | ||
src/archive/tar/writer_test.go | 27 ++++++++++++++++++ | ||
6 files changed, 56 insertions(+), 3 deletions(-) | ||
create mode 100644 src/archive/tar/testdata/pax-bad-hdr-large.tar.bz2 | ||
|
||
diff --git a/src/archive/tar/format.go b/src/archive/tar/format.go | ||
index cfe24a5e1d..6642364de1 100644 | ||
--- a/src/archive/tar/format.go | ||
+++ b/src/archive/tar/format.go | ||
@@ -143,6 +143,10 @@ const ( | ||
blockSize = 512 // Size of each block in a tar stream | ||
nameSize = 100 // Max length of the name field in USTAR format | ||
prefixSize = 155 // Max length of the prefix field in USTAR format | ||
+ | ||
+ // Max length of a special file (PAX header, GNU long name or link). | ||
+ // This matches the limit used by libarchive. | ||
+ maxSpecialFileSize = 1 << 20 | ||
) | ||
|
||
// blockPadding computes the number of bytes needed to pad offset up to the | ||
diff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go | ||
index 1b1d5b4689..f645af8016 100644 | ||
--- a/src/archive/tar/reader.go | ||
+++ b/src/archive/tar/reader.go | ||
@@ -103,7 +103,7 @@ func (tr *Reader) next() (*Header, error) { | ||
continue // This is a meta header affecting the next header | ||
case TypeGNULongName, TypeGNULongLink: | ||
format.mayOnlyBe(FormatGNU) | ||
- realname, err := io.ReadAll(tr) | ||
+ realname, err := readSpecialFile(tr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
@@ -293,7 +293,7 @@ func mergePAX(hdr *Header, paxHdrs map[string]string) (err error) { | ||
// parsePAX parses PAX headers. | ||
// If an extended header (type 'x') is invalid, ErrHeader is returned | ||
func parsePAX(r io.Reader) (map[string]string, error) { | ||
- buf, err := io.ReadAll(r) | ||
+ buf, err := readSpecialFile(r) | ||
if err != nil { | ||
return nil, err | ||
} | ||
@@ -826,6 +826,16 @@ func tryReadFull(r io.Reader, b []byte) (n int, err error) { | ||
return n, err | ||
} | ||
|
||
+// readSpecialFile is like io.ReadAll except it returns | ||
+// ErrFieldTooLong if more than maxSpecialFileSize is read. | ||
+func readSpecialFile(r io.Reader) ([]byte, error) { | ||
+ buf, err := io.ReadAll(io.LimitReader(r, maxSpecialFileSize+1)) | ||
+ if len(buf) > maxSpecialFileSize { | ||
+ return nil, ErrFieldTooLong | ||
+ } | ||
+ return buf, err | ||
+} | ||
+ | ||
// discard skips n bytes in r, reporting an error if unable to do so. | ||
func discard(r io.Reader, n int64) error { | ||
// If possible, Seek to the last byte before the end of the data section. | ||
diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go | ||
index 789ddc1bc0..5a644a43a4 100644 | ||
--- a/src/archive/tar/reader_test.go | ||
+++ b/src/archive/tar/reader_test.go | ||
@@ -6,6 +6,7 @@ package tar | ||
|
||
import ( | ||
"bytes" | ||
+ "compress/bzip2" | ||
"crypto/md5" | ||
"errors" | ||
"fmt" | ||
@@ -243,6 +244,9 @@ func TestReader(t *testing.T) { | ||
}, { | ||
file: "testdata/pax-bad-hdr-file.tar", | ||
err: ErrHeader, | ||
+ }, { | ||
+ file: "testdata/pax-bad-hdr-large.tar.bz2", | ||
+ err: ErrFieldTooLong, | ||
}, { | ||
file: "testdata/pax-bad-mtime-file.tar", | ||
err: ErrHeader, | ||
@@ -625,9 +629,14 @@ func TestReader(t *testing.T) { | ||
} | ||
defer f.Close() | ||
|
||
+ var fr io.Reader = f | ||
+ if strings.HasSuffix(v.file, ".bz2") { | ||
+ fr = bzip2.NewReader(fr) | ||
+ } | ||
+ | ||
// Capture all headers and checksums. | ||
var ( | ||
- tr = NewReader(f) | ||
+ tr = NewReader(fr) | ||
hdrs []*Header | ||
chksums []string | ||
rdbuf = make([]byte, 8) | ||
diff --git a/src/archive/tar/testdata/pax-bad-hdr-large.tar.bz2 b/src/archive/tar/testdata/pax-bad-hdr-large.tar.bz2 | ||
new file mode 100644 | ||
index 0000000000000000000000000000000000000000..06bf710d3ae4e96a27487124f08e30c9e318699d | ||
GIT binary patch | ||
literal 156 | ||
zcmV;N0Av3`T4*^jL0KkKS;SwlM*sj&-;n5#Kmq^806<7UW<Xv*06+)`AOM6LQB%`R | ||
zAoUtF^&Y00G(AA7R6Rgw0K{a`;)ySob}qf{K(WW#h);2a@?<AStKizfO^|VdbRoJj | ||
zqj=52lgiv7w2N0MDEF-8t!>m)Y~!#90LDZj0F4RNS<;o$l$z=JG_q>Xyl@Bs{9VZu | ||
K;X*?Ze#IONT1LeH | ||
|
||
literal 0 | ||
HcmV?d00001 | ||
|
||
diff --git a/src/archive/tar/writer.go b/src/archive/tar/writer.go | ||
index e80498d03e..893eac00ae 100644 | ||
--- a/src/archive/tar/writer.go | ||
+++ b/src/archive/tar/writer.go | ||
@@ -199,6 +199,9 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error { | ||
flag = TypeXHeader | ||
} | ||
data := buf.String() | ||
+ if len(data) > maxSpecialFileSize { | ||
+ return ErrFieldTooLong | ||
+ } | ||
if err := tw.writeRawFile(name, data, flag, FormatPAX); err != nil || isGlobal { | ||
return err // Global headers return here | ||
} | ||
diff --git a/src/archive/tar/writer_test.go b/src/archive/tar/writer_test.go | ||
index a00f02d8fa..4e709e5cac 100644 | ||
--- a/src/archive/tar/writer_test.go | ||
+++ b/src/archive/tar/writer_test.go | ||
@@ -1006,6 +1006,33 @@ func TestIssue12594(t *testing.T) { | ||
} | ||
} | ||
|
||
+func TestWriteLongHeader(t *testing.T) { | ||
+ for _, test := range []struct { | ||
+ name string | ||
+ h *Header | ||
+ }{{ | ||
+ name: "name too long", | ||
+ h: &Header{Name: strings.Repeat("a", maxSpecialFileSize)}, | ||
+ }, { | ||
+ name: "linkname too long", | ||
+ h: &Header{Linkname: strings.Repeat("a", maxSpecialFileSize)}, | ||
+ }, { | ||
+ name: "uname too long", | ||
+ h: &Header{Uname: strings.Repeat("a", maxSpecialFileSize)}, | ||
+ }, { | ||
+ name: "gname too long", | ||
+ h: &Header{Gname: strings.Repeat("a", maxSpecialFileSize)}, | ||
+ }, { | ||
+ name: "PAX header too long", | ||
+ h: &Header{PAXRecords: map[string]string{"GOLANG.x": strings.Repeat("a", maxSpecialFileSize)}}, | ||
+ }} { | ||
+ w := NewWriter(io.Discard) | ||
+ if err := w.WriteHeader(test.h); err != ErrFieldTooLong { | ||
+ t.Errorf("%v: w.WriteHeader() = %v, want ErrFieldTooLong", test.name, err) | ||
+ } | ||
+ } | ||
+} | ||
+ | ||
// testNonEmptyWriter wraps an io.Writer and ensures that | ||
// Write is never called with an empty buffer. | ||
type testNonEmptyWriter struct{ io.Writer } | ||
-- | ||
2.37.3 | ||
|