Skip to content

Commit

Permalink
archive/tar: limit size of headers
Browse files Browse the repository at this point in the history
# AWS EKS
Backported To: go-1.15.15-eks
Backported On: Wed, 5 Oct 2022
Backported By: rcrozean@amazon.com
Backported From: release-branch.go1.15
Source Commit: golang@0a72381
EKS Patch Source Commit: aws/eks-distro-build-tooling@1de4158

For building an internal version of go1.15, we removed the binary
information from this patch caused by ./src/archive/tar/pax-bad-hdr-large.tar.bz2
it was added to the repo:
https://github.com/aws/eks-distro-build-tooling/projects/golang/go/1.15/rpmbuild/SOURCE/pax-bad-hdr-large.tar.bz2

# Originial 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 golang#54853
Fixes golang#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>
  • Loading branch information
neild authored and rcrozean committed Oct 12, 2022
1 parent e141d50 commit 4697865
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 3 deletions.
4 changes: 4 additions & 0 deletions src/archive/tar/format.go
Expand Up @@ -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
Expand Down
14 changes: 12 additions & 2 deletions src/archive/tar/reader.go
Expand Up @@ -104,7 +104,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 := ioutil.ReadAll(tr)
realname, err := readSpecialFile(tr)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -294,7 +294,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 := ioutil.ReadAll(r)
buf, err := readSpecialFile(r)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -827,6 +827,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 := ioutil.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.
Expand Down
11 changes: 10 additions & 1 deletion src/archive/tar/reader_test.go
Expand Up @@ -6,6 +6,7 @@ package tar

import (
"bytes"
"compress/bzip2"
"crypto/md5"
"errors"
"fmt"
Expand Down Expand Up @@ -244,6 +245,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,
Expand Down Expand Up @@ -626,9 +630,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)
Expand Down
3 changes: 3 additions & 0 deletions src/archive/tar/writer.go
Expand Up @@ -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
}
Expand Down
27 changes: 27 additions & 0 deletions src/archive/tar/writer_test.go
Expand Up @@ -1007,6 +1007,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(ioutil.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 }
Expand Down

0 comments on commit 4697865

Please sign in to comment.