diff mbox series

[scarthgap,3/3] go: fix CVE-2026-32288

Message ID 20260612131618.664716-3-sudumbha@cisco.com
State New
Headers show
Series [scarthgap,1/3] go: fix CVE-2025-58183 | expand

Commit Message

From: Sudhir Dumbhare <sudumbha@cisco.com>

This patch applies the upstream fix [1], as referenced in [2],
to address unbounded sparse map handling in `archive/tar`.

[1] https://github.com/golang/go/commit/82b0cdb7411ea2cf02d3a45e6983cc7c8c009d9e
[2] https://security-tracker.debian.org/tracker/CVE-2026-32288

Reference:
https://nvd.nist.gov/vuln/detail/CVE-2026-32288

Signed-off-by: Sudhir Dumbhare <sudumbha@cisco.com>
---
 meta/recipes-devtools/go/go-1.22.12.inc       |   1 +
 .../go/go/CVE-2026-32288.patch                | 162 ++++++++++++++++++
 2 files changed, 163 insertions(+)
 create mode 100644 meta/recipes-devtools/go/go/CVE-2026-32288.patch
diff mbox series

Patch

diff --git a/meta/recipes-devtools/go/go-1.22.12.inc b/meta/recipes-devtools/go/go-1.22.12.inc
index 7dd1c021cb..b3cb3b58b4 100644
--- a/meta/recipes-devtools/go/go-1.22.12.inc
+++ b/meta/recipes-devtools/go/go-1.22.12.inc
@@ -43,6 +43,7 @@  SRC_URI += "\
     file://CVE-2025-68121_p3.patch \
     file://CVE-2025-58183.patch \
     file://CVE-2026-25679.patch \
+    file://CVE-2026-32288.patch \
 "
 SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71"
 
diff --git a/meta/recipes-devtools/go/go/CVE-2026-32288.patch b/meta/recipes-devtools/go/go/CVE-2026-32288.patch
new file mode 100644
index 0000000000..7b838db345
--- /dev/null
+++ b/meta/recipes-devtools/go/go/CVE-2026-32288.patch
@@ -0,0 +1,162 @@ 
+From 12bbeb57c20d32519c3f891b428c6f7765db8f55 Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Mon, 23 Mar 2026 13:12:44 -0700
+Subject: [PATCH] [release-branch.go1.25] archive/tar: limit the number of
+ old GNU sparse format entries
+
+We did not set a limit on the maximum size of sparse maps in
+the old GNU sparse format. Set a limit based on the cumulative
+size of the extension blocks used to encode the map (consistent
+with how we limit the sparse map size for other formats).
+
+Add an additional limit to the total number of sparse file entries,
+regardless of encoding, to all sparse formats.
+
+Thanks to Colin Walters (walters@verbum.org),
+Uuganbayar Lkhamsuren (https://github.com/uug4na),
+and Jakub Ciolek for reporting this issue.
+
+Fixes #78301
+Fixes CVE-2026-32288
+
+CVE: CVE-2026-32288
+Upstream-Status: Backport [https://github.com/golang/go/commit/82b0cdb7411ea2cf02d3a45e6983cc7c8c009d9e]
+
+Change-Id: I84877345d7b41cc60c58771860ba70e16a6a6964
+Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3901
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/4003
+Reviewed-by: Nicholas Husin <husin@google.com>
+Reviewed-by: Neal Patel <nealpatel@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/763554
+TryBot-Bypass: Gopher Robot <gobot@golang.org>
+Auto-Submit: Gopher Robot <gobot@golang.org>
+Reviewed-by: Junyang Shao <shaojunyang@google.com>
+Reviewed-by: David Chase <drchase@google.com>
+(cherry picked from commit 82b0cdb7411ea2cf02d3a45e6983cc7c8c009d9e)
+Signed-off-by: Sudhir Dumbhare <sudumbha@cisco.com>
+---
+ src/archive/tar/format.go      |  6 ++++++
+ src/archive/tar/reader.go      | 28 ++++++++++++++++++++++++----
+ src/archive/tar/reader_test.go | 11 +++++++++++
+ 3 files changed, 41 insertions(+), 4 deletions(-)
+
+diff --git a/src/archive/tar/format.go b/src/archive/tar/format.go
+index 9954b4d9f55..32e58a9d9b4 100644
+--- a/src/archive/tar/format.go
++++ b/src/archive/tar/format.go
+@@ -147,6 +147,12 @@ const (
+ 	// Max length of a special file (PAX header, GNU long name or link).
+ 	// This matches the limit used by libarchive.
+ 	maxSpecialFileSize = 1 << 20
++
++	// Maximum number of sparse file entries.
++	// We should never actually hit this limit
++	// (every sparse encoding will first be limited by maxSpecialFileSize),
++	// but this adds an additional layer of defense.
++	maxSparseFileEntries = 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 71d0b20b76d..3bb8d62106c 100644
+--- a/src/archive/tar/reader.go
++++ b/src/archive/tar/reader.go
+@@ -490,7 +490,8 @@ func (tr *Reader) readOldGNUSparseMap(hdr *Header, blk *block) (sparseDatas, err
+ 	}
+ 	s := blk.toGNU().sparse()
+ 	spd := make(sparseDatas, 0, s.maxEntries())
+-	for {
++	totalSize := len(s)
++	for totalSize < maxSpecialFileSize {
+ 		for i := 0; i < s.maxEntries(); i++ {
+ 			// This termination condition is identical to GNU and BSD tar.
+ 			if s.entry(i).offset()[0] == 0x00 {
+@@ -501,7 +502,11 @@ func (tr *Reader) readOldGNUSparseMap(hdr *Header, blk *block) (sparseDatas, err
+ 			if p.err != nil {
+ 				return nil, p.err
+ 			}
+-			spd = append(spd, sparseEntry{Offset: offset, Length: length})
++			var err error
++			spd, err = appendSparseEntry(spd, sparseEntry{Offset: offset, Length: length})
++			if err != nil {
++				return nil, err
++			}
+ 		}
+ 
+ 		if s.isExtended()[0] > 0 {
+@@ -510,10 +515,12 @@ func (tr *Reader) readOldGNUSparseMap(hdr *Header, blk *block) (sparseDatas, err
+ 				return nil, err
+ 			}
+ 			s = blk.toSparse()
++			totalSize += len(s)
+ 			continue
+ 		}
+ 		return spd, nil // Done
+ 	}
++	return nil, errSparseTooLong
+ }
+ 
+ // readGNUSparseMap1x0 reads the sparse map as stored in GNU's PAX sparse format
+@@ -586,7 +593,10 @@ func readGNUSparseMap1x0(r io.Reader) (sparseDatas, error) {
+ 		if err1 != nil || err2 != nil {
+ 			return nil, ErrHeader
+ 		}
+-		spd = append(spd, sparseEntry{Offset: offset, Length: length})
++		spd, err = appendSparseEntry(spd, sparseEntry{Offset: offset, Length: length})
++		if err != nil {
++			return nil, err
++		}
+ 	}
+ 	return spd, nil
+ }
+@@ -620,12 +630,22 @@ func readGNUSparseMap0x1(paxHdrs map[string]string) (sparseDatas, error) {
+ 		if err1 != nil || err2 != nil {
+ 			return nil, ErrHeader
+ 		}
+-		spd = append(spd, sparseEntry{Offset: offset, Length: length})
++		spd, err = appendSparseEntry(spd, sparseEntry{Offset: offset, Length: length})
++		if err != nil {
++			return nil, err
++		}
+ 		sparseMap = sparseMap[2:]
+ 	}
+ 	return spd, nil
+ }
+ 
++func appendSparseEntry(spd sparseDatas, ent sparseEntry) (sparseDatas, error) {
++	if len(spd) >= maxSparseFileEntries {
++		return nil, errSparseTooLong
++	}
++	return append(spd, ent), nil
++}
++
+ // Read reads from the current file in the tar archive.
+ // It returns (0, io.EOF) when it reaches the end of that file,
+ // until [Next] is called to advance to the next file.
+diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go
+index 7e0462c3f88..4a527766ba8 100644
+--- a/src/archive/tar/reader_test.go
++++ b/src/archive/tar/reader_test.go
+@@ -1126,6 +1126,17 @@ func TestReadOldGNUSparseMap(t *testing.T) {
+ 		input: makeInput(FormatGNU, "",
+ 			makeSparseStrings(sparseDatas{{10 << 30, 512}, {20 << 30, 512}})...),
+ 		wantMap: sparseDatas{{10 << 30, 512}, {20 << 30, 512}},
++	}, {
++		input: makeInput(FormatGNU, "",
++			makeSparseStrings(func() sparseDatas {
++				var datas sparseDatas
++				// This is more than enough entries to exceed our limit.
++				for i := range int64(1 << 20) {
++					datas = append(datas, sparseEntry{i * 2, (i * 2) + 1})
++				}
++				return datas
++			}())...),
++		wantErr: errSparseTooLong,
+ 	}}
+ 
+ 	for i, v := range vectors {
+-- 
+2.35.6
+