|
| 1 | +From 042465900fcbb246c602c856ccd924ddf093947e Mon Sep 17 00:00:00 2001 |
| 2 | +From: Muhammad Falak R Wani < [email protected]> |
| 3 | +Date: Tue, 9 Jul 2024 19:27:30 +0530 |
| 4 | +Subject: [PATCH] archive/tar: limit size of headers |
| 5 | + |
| 6 | +Set a 1MiB limit on special file blocks (PAX headers, GNU long names, |
| 7 | +GNU link names), to avoid reading arbitrarily large amounts of data |
| 8 | +into memory. |
| 9 | + |
| 10 | +Thanks to Adam Korczynski (ADA Logics) and OSS-Fuzz for reporting |
| 11 | +this issue. |
| 12 | + |
| 13 | +Fixes CVE-2022-2879 |
| 14 | +Updates #54853 |
| 15 | +Fixes #55925 |
| 16 | + |
| 17 | +Signed-off-by: Muhammad Falak R Wani < [email protected]> |
| 18 | +Signed-off-by: Thien Trung Vuong < [email protected]> |
| 19 | +--- |
| 20 | + .../vbatts/tar-split/archive/tar/format.go | 4 ++++ |
| 21 | + .../vbatts/tar-split/archive/tar/reader.go | 14 ++++++++++++-- |
| 22 | + .../vbatts/tar-split/archive/tar/writer.go | 3 +++ |
| 23 | + 3 files changed, 19 insertions(+), 2 deletions(-) |
| 24 | + |
| 25 | +diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/format.go b/vendor/github.com/vbatts/tar-split/archive/tar/format.go |
| 26 | +index 1f89d0c..6097798 100644 |
| 27 | +--- a/vendor/github.com/vbatts/tar-split/archive/tar/format.go |
| 28 | ++++ b/vendor/github.com/vbatts/tar-split/archive/tar/format.go |
| 29 | +@@ -143,6 +143,10 @@ const ( |
| 30 | + blockSize = 512 // Size of each block in a tar stream |
| 31 | + nameSize = 100 // Max length of the name field in USTAR format |
| 32 | + prefixSize = 155 // Max length of the prefix field in USTAR format |
| 33 | ++ |
| 34 | ++ // Max length of a special file (PAX header, GNU long name or link). |
| 35 | ++ // This matches the limit used by libarchive. |
| 36 | ++ maxSpecialFileSize = 1 << 20 |
| 37 | + ) |
| 38 | + |
| 39 | + // blockPadding computes the number of bytes needed to pad offset up to the |
| 40 | +diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/reader.go b/vendor/github.com/vbatts/tar-split/archive/tar/reader.go |
| 41 | +index af006fc..2baa0d5 100644 |
| 42 | +--- a/vendor/github.com/vbatts/tar-split/archive/tar/reader.go |
| 43 | ++++ b/vendor/github.com/vbatts/tar-split/archive/tar/reader.go |
| 44 | +@@ -139,7 +139,7 @@ func (tr *Reader) next() (*Header, error) { |
| 45 | + continue // This is a meta header affecting the next header |
| 46 | + case TypeGNULongName, TypeGNULongLink: |
| 47 | + format.mayOnlyBe(FormatGNU) |
| 48 | +- realname, err := ioutil.ReadAll(tr) |
| 49 | ++ realname, err := readSpecialFile(tr) |
| 50 | + if err != nil { |
| 51 | + return nil, err |
| 52 | + } |
| 53 | +@@ -333,7 +333,7 @@ func mergePAX(hdr *Header, paxHdrs map[string]string) (err error) { |
| 54 | + // parsePAX parses PAX headers. |
| 55 | + // If an extended header (type 'x') is invalid, ErrHeader is returned |
| 56 | + func parsePAX(r io.Reader) (map[string]string, error) { |
| 57 | +- buf, err := ioutil.ReadAll(r) |
| 58 | ++ buf, err := readSpecialFile(r) |
| 59 | + if err != nil { |
| 60 | + return nil, err |
| 61 | + } |
| 62 | +@@ -884,6 +884,16 @@ func tryReadFull(r io.Reader, b []byte) (n int, err error) { |
| 63 | + return n, err |
| 64 | + } |
| 65 | + |
| 66 | ++// readSpecialFile is like io.ReadAll except it returns |
| 67 | ++// ErrFieldTooLong if more than maxSpecialFileSize is read. |
| 68 | ++func readSpecialFile(r io.Reader) ([]byte, error) { |
| 69 | ++ buf, err := io.ReadAll(io.LimitReader(r, maxSpecialFileSize+1)) |
| 70 | ++ if len(buf) > maxSpecialFileSize { |
| 71 | ++ return nil, ErrFieldTooLong |
| 72 | ++ } |
| 73 | ++ return buf, err |
| 74 | ++} |
| 75 | ++ |
| 76 | + // discard skips n bytes in r, reporting an error if unable to do so. |
| 77 | + func discard(tr *Reader, n int64) error { |
| 78 | + var seekSkipped, copySkipped int64 |
| 79 | +diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/writer.go b/vendor/github.com/vbatts/tar-split/archive/tar/writer.go |
| 80 | +index e80498d..893eac0 100644 |
| 81 | +--- a/vendor/github.com/vbatts/tar-split/archive/tar/writer.go |
| 82 | ++++ b/vendor/github.com/vbatts/tar-split/archive/tar/writer.go |
| 83 | +@@ -199,6 +199,9 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error { |
| 84 | + flag = TypeXHeader |
| 85 | + } |
| 86 | + data := buf.String() |
| 87 | ++ if len(data) > maxSpecialFileSize { |
| 88 | ++ return ErrFieldTooLong |
| 89 | ++ } |
| 90 | + if err := tw.writeRawFile(name, data, flag, FormatPAX); err != nil || isGlobal { |
| 91 | + return err // Global headers return here |
| 92 | + } |
| 93 | +-- |
| 94 | +2.40.1 |
| 95 | + |
0 commit comments