mirror of
https://github.com/golang/go.git
synced 2025-10-19 11:03:18 +00:00
[release-branch.go1.24] archive/tar: set a limit on the size of GNU sparse file 1.0 regions
Sparse files in tar archives contain only the non-zero components of the file. There are several different encodings for sparse files. When reading GNU tar pax 1.0 sparse files, archive/tar did not set a limit on the size of the sparse region data. A malicious archive containing a large number of sparse blocks could cause archive/tar to read an unbounded amount of data from the archive into memory. Since a malicious input can be highly compressable, a small compressed input could cause very large allocations. Cap the size of the sparse block data to the same limit used for PAX headers (1 MiB). Thanks to Harshit Gupta (Mr HAX) (https://www.linkedin.com/in/iam-harshit-gupta/) for reporting this issue. Fixes CVE-2025-58183 For #75677 Fixes #75710 Change-Id: I70b907b584a7b8676df8a149a1db728ae681a770 Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2800 Reviewed-by: Roland Shoemaker <bracewell@google.com> Reviewed-by: Nicholas Husin <husin@google.com> Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/2967 Reviewed-by: Damien Neil <dneil@google.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/709843 Reviewed-by: Carlos Amedee <carlos@golang.org> TryBot-Bypass: Michael Pratt <mpratt@google.com> Auto-Submit: Michael Pratt <mpratt@google.com>
This commit is contained in:
parent
74d4d836b9
commit
613e746327
4 changed files with 13 additions and 2 deletions
|
@ -39,6 +39,7 @@ var (
|
|||
errMissData = errors.New("archive/tar: sparse file references non-existent data")
|
||||
errUnrefData = errors.New("archive/tar: sparse file contains unreferenced data")
|
||||
errWriteHole = errors.New("archive/tar: write non-NUL byte in sparse hole")
|
||||
errSparseTooLong = errors.New("archive/tar: sparse map too long")
|
||||
)
|
||||
|
||||
type headerError []string
|
||||
|
|
|
@ -531,12 +531,17 @@ func readGNUSparseMap1x0(r io.Reader) (sparseDatas, error) {
|
|||
cntNewline int64
|
||||
buf bytes.Buffer
|
||||
blk block
|
||||
totalSize int
|
||||
)
|
||||
|
||||
// feedTokens copies data in blocks from r into buf until there are
|
||||
// at least cnt newlines in buf. It will not read more blocks than needed.
|
||||
feedTokens := func(n int64) error {
|
||||
for cntNewline < n {
|
||||
totalSize += len(blk)
|
||||
if totalSize > maxSpecialFileSize {
|
||||
return errSparseTooLong
|
||||
}
|
||||
if _, err := mustReadFull(r, blk[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -569,8 +574,8 @@ func readGNUSparseMap1x0(r io.Reader) (sparseDatas, error) {
|
|||
}
|
||||
|
||||
// Parse for all member entries.
|
||||
// numEntries is trusted after this since a potential attacker must have
|
||||
// committed resources proportional to what this library used.
|
||||
// numEntries is trusted after this since feedTokens limits the number of
|
||||
// tokens based on maxSpecialFileSize.
|
||||
if err := feedTokens(2 * numEntries); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -621,6 +621,11 @@ func TestReader(t *testing.T) {
|
|||
},
|
||||
Format: FormatPAX,
|
||||
}},
|
||||
}, {
|
||||
// Small compressed file that uncompresses to
|
||||
// a file with a very large GNU 1.0 sparse map.
|
||||
file: "testdata/gnu-sparse-many-zeros.tar.bz2",
|
||||
err: errSparseTooLong,
|
||||
}}
|
||||
|
||||
for _, v := range vectors {
|
||||
|
|
BIN
src/archive/tar/testdata/gnu-sparse-many-zeros.tar.bz2
vendored
Normal file
BIN
src/archive/tar/testdata/gnu-sparse-many-zeros.tar.bz2
vendored
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue