|
| 1 | +From 2c9e7f55aa25221e776bad497448442dde6b2ef0 Mon Sep 17 00:00:00 2001 |
| 2 | +From: AllSpark <allspark@microsoft.com> |
| 3 | +Date: Sat, 15 Nov 2025 05:50:08 +0000 |
| 4 | +Subject: [PATCH] archive/tar: set a limit on the size of GNU sparse file 1.0 |
| 5 | + regions |
| 6 | + |
| 7 | +Cap the size of the sparse block data to the same limit used for PAX headers (1 MiB). Add errSparseTooLong error and enforce maxSpecialFileSize when reading GNU PAX 1.0 sparse maps. Update comments accordingly. |
| 8 | + |
| 9 | +Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> |
| 10 | +Upstream-reference: AI Backport of https://github.com/vbatts/tar-split/commit/55da7d6b43bd806ee785d783bdf66bcf302af118.patch |
| 11 | +--- |
| 12 | + .../vbatts/tar-split/archive/tar/common.go | 3 +++ |
| 13 | + .../vbatts/tar-split/archive/tar/format.go | 3 +++ |
| 14 | + .../vbatts/tar-split/archive/tar/reader.go | 12 ++++++++++-- |
| 15 | + 3 files changed, 16 insertions(+), 2 deletions(-) |
| 16 | + |
| 17 | +diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/common.go b/vendor/github.com/vbatts/tar-split/archive/tar/common.go |
| 18 | +index dee9e47..bb43fbe 100644 |
| 19 | +--- a/vendor/github.com/vbatts/tar-split/archive/tar/common.go |
| 20 | ++++ b/vendor/github.com/vbatts/tar-split/archive/tar/common.go |
| 21 | +@@ -34,6 +34,9 @@ var ( |
| 22 | + errMissData = errors.New("archive/tar: sparse file references non-existent data") |
| 23 | + errUnrefData = errors.New("archive/tar: sparse file contains unreferenced data") |
| 24 | + errWriteHole = errors.New("archive/tar: write non-NUL byte in sparse hole") |
| 25 | ++ // errSparseTooLong is returned when the GNU PAX 1.0 sparse map exceeds the |
| 26 | ++ // maximum permitted size for special file data (same as PAX headers). |
| 27 | ++ errSparseTooLong = errors.New("archive/tar: sparse map too long") |
| 28 | + ) |
| 29 | + |
| 30 | + type headerError []string |
| 31 | +diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/format.go b/vendor/github.com/vbatts/tar-split/archive/tar/format.go |
| 32 | +index 1f89d0c..62dc505 100644 |
| 33 | +--- a/vendor/github.com/vbatts/tar-split/archive/tar/format.go |
| 34 | ++++ b/vendor/github.com/vbatts/tar-split/archive/tar/format.go |
| 35 | +@@ -143,6 +143,9 @@ const ( |
| 36 | + blockSize = 512 // Size of each block in a tar stream |
| 37 | + nameSize = 100 // Max length of the name field in USTAR format |
| 38 | + prefixSize = 155 // Max length of the prefix field in USTAR format |
| 39 | ++ // maxSpecialFileSize caps the size of special file data, such as PAX headers. |
| 40 | ++ // This is set to 1 MiB to avoid excessive memory allocation on malicious inputs. |
| 41 | ++ maxSpecialFileSize = 1 << 20 |
| 42 | + ) |
| 43 | + |
| 44 | + // blockPadding computes the number of bytes needed to pad offset up to the |
| 45 | +diff --git a/vendor/github.com/vbatts/tar-split/archive/tar/reader.go b/vendor/github.com/vbatts/tar-split/archive/tar/reader.go |
| 46 | +index fcf3215..176b40f 100644 |
| 47 | +--- a/vendor/github.com/vbatts/tar-split/archive/tar/reader.go |
| 48 | ++++ b/vendor/github.com/vbatts/tar-split/archive/tar/reader.go |
| 49 | +@@ -577,12 +577,20 @@ func readGNUSparseMap1x0(r io.Reader) (sparseDatas, error) { |
| 50 | + cntNewline int64 |
| 51 | + buf bytes.Buffer |
| 52 | + blk block |
| 53 | ++ // totalSize tracks the total size of the sparse map data read. |
| 54 | ++ totalSize int |
| 55 | + ) |
| 56 | + |
| 57 | + // feedTokens copies data in blocks from r into buf until there are |
| 58 | + // at least cnt newlines in buf. It will not read more blocks than needed. |
| 59 | + feedTokens := func(n int64) error { |
| 60 | + for cntNewline < n { |
| 61 | ++ // Increase totalSize by the size of the block to enforce a cap |
| 62 | ++ totalSize += len(blk) |
| 63 | ++ // Enforce the same cap as PAX header size: maxSpecialFileSize |
| 64 | ++ if totalSize > maxSpecialFileSize { |
| 65 | ++ return errSparseTooLong |
| 66 | ++ } |
| 67 | + if _, err := mustReadFull(r, blk[:]); err != nil { |
| 68 | + return err |
| 69 | + } |
| 70 | +@@ -615,8 +623,8 @@ func readGNUSparseMap1x0(r io.Reader) (sparseDatas, error) { |
| 71 | + } |
| 72 | + |
| 73 | + // Parse for all member entries. |
| 74 | +- // numEntries is trusted after this since a potential attacker must have |
| 75 | +- // committed resources proportional to what this library used. |
| 76 | ++ // numEntries is trusted after this since feedTokens limits the number of |
| 77 | ++ // tokens based on maxSpecialFileSize. |
| 78 | + if err := feedTokens(2 * numEntries); err != nil { |
| 79 | + return nil, err |
| 80 | + } |
| 81 | +-- |
| 82 | +2.45.4 |
| 83 | + |
0 commit comments