From 108dbb4e9030ff347afd3eff7d14c67f6855b3d2 Mon Sep 17 00:00:00 2001 From: jykanase Date: Sat, 18 Apr 2026 01:20:26 +0530 Subject: [PATCH] Upgrade `containerd2` version to 2.1.6 (#16719) (cherry picked from commit 61bee1cb1b2eb6bacee223a193a840bd9086fb26) --- SPECS/containerd2/CVE-2024-25621.patch | 111 --- SPECS/containerd2/CVE-2024-40635.patch | 174 ----- SPECS/containerd2/CVE-2024-45338.patch | 80 -- SPECS/containerd2/CVE-2025-22872.patch | 42 - SPECS/containerd2/CVE-2025-27144.patch | 49 -- SPECS/containerd2/CVE-2025-47291.patch | 220 ------ SPECS/containerd2/CVE-2025-47911.patch | 100 --- SPECS/containerd2/CVE-2025-58190.patch | 126 --- SPECS/containerd2/CVE-2025-64329.patch | 73 -- SPECS/containerd2/CVE-2026-35469.patch | 727 ------------------ SPECS/containerd2/containerd2.signatures.json | 4 +- SPECS/containerd2/containerd2.spec | 30 +- .../fix-credential-leak-in-cri-errors.patch | 292 ------- .../multi-snapshotters-support.patch | 50 +- cgmanifest.json | 4 +- 15 files changed, 43 insertions(+), 2039 deletions(-) delete mode 100644 SPECS/containerd2/CVE-2024-25621.patch delete mode 100644 SPECS/containerd2/CVE-2024-40635.patch delete mode 100644 SPECS/containerd2/CVE-2024-45338.patch delete mode 100644 SPECS/containerd2/CVE-2025-22872.patch delete mode 100644 SPECS/containerd2/CVE-2025-27144.patch delete mode 100644 SPECS/containerd2/CVE-2025-47291.patch delete mode 100644 SPECS/containerd2/CVE-2025-47911.patch delete mode 100644 SPECS/containerd2/CVE-2025-58190.patch delete mode 100644 SPECS/containerd2/CVE-2025-64329.patch delete mode 100644 SPECS/containerd2/CVE-2026-35469.patch diff --git a/SPECS/containerd2/CVE-2024-25621.patch b/SPECS/containerd2/CVE-2024-25621.patch deleted file mode 100644 index d07a78a1297..00000000000 --- a/SPECS/containerd2/CVE-2024-25621.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 46223b256bfb3f42e193d947d1b1ef551260749f Mon Sep 17 00:00:00 2001 -From: Akihiro Suda -Date: Mon, 27 Oct 2025 16:42:59 +0900 -Subject: [PATCH] Fix directory permissions - -- Create /var/lib/containerd with 0o700 (was: 0o711). -- Create config.TempDir with 0o700 (was: 0o711). -- Create /run/containerd/io.containerd.grpc.v1.cri with 0o700 (was: 0o755). -- Create /run/containerd/io.containerd.sandbox.controller.v1.shim with 0o700 (was: 0o711). -- Leave /run/containerd and /run/containerd/io.containerd.runtime.v2.task created with 0o711, - as required by userns-remapped containers. - /run/containerd/io.containerd.runtime.v2.task// is created with: - - 0o700 for non-userns-remapped containers - - 0o710 for userns-remapped containers with the remapped root group as the owner group. - -Signed-off-by: Akihiro Suda -Signed-off-by: Azure Linux Security Servicing Account -Upstream-reference: https://github.com/containerd/containerd/commit/7c59e8e9e970d38061a77b586b23655c352bfec5.patch ---- - cmd/containerd/server/server.go | 14 ++++++++++++-- - core/runtime/v2/task_manager.go | 2 ++ - plugins/cri/runtime/plugin.go | 7 +++++++ - plugins/sandbox/controller.go | 6 +++++- - 4 files changed, 26 insertions(+), 3 deletions(-) - -diff --git a/cmd/containerd/server/server.go b/cmd/containerd/server/server.go -index 9f38cb3..c9e3698 100644 ---- a/cmd/containerd/server/server.go -+++ b/cmd/containerd/server/server.go -@@ -81,10 +81,16 @@ func CreateTopLevelDirectories(config *srvconfig.Config) error { - return errors.New("root and state must be different paths") - } - -- if err := sys.MkdirAllWithACL(config.Root, 0o711); err != nil { -+ if err := sys.MkdirAllWithACL(config.Root, 0o700); err != nil { -+ return err -+ } -+ // chmod is needed for upgrading from an older release that created the dir with 0o711 -+ if err := os.Chmod(config.Root, 0o700); err != nil { - return err - } - -+ // For supporting userns-remapped containers, the state dir cannot be just mkdired with 0o700. -+ // Each of plugins creates a dedicated directory beneath the state dir with appropriate permission bits. - if err := sys.MkdirAllWithACL(config.State, 0o711); err != nil { - return err - } -@@ -99,7 +105,11 @@ func CreateTopLevelDirectories(config *srvconfig.Config) error { - } - - if config.TempDir != "" { -- if err := sys.MkdirAllWithACL(config.TempDir, 0o711); err != nil { -+ if err := sys.MkdirAllWithACL(config.TempDir, 0o700); err != nil { -+ return err -+ } -+ // chmod is needed for upgrading from an older release that created the dir with 0o711 -+ if err := os.Chmod(config.Root, 0o700); err != nil { - return err - } - if runtime.GOOS == "windows" { -diff --git a/core/runtime/v2/task_manager.go b/core/runtime/v2/task_manager.go -index f396ced..024763a 100644 ---- a/core/runtime/v2/task_manager.go -+++ b/core/runtime/v2/task_manager.go -@@ -74,6 +74,8 @@ func init() { - shimManager := shimManagerI.(*ShimManager) - root, state := ic.Properties[plugins.PropertyRootDir], ic.Properties[plugins.PropertyStateDir] - for _, d := range []string{root, state} { -+ // root: the parent of this directory is created as 0o700, not 0o711. -+ // state: the parent of this directory is created as 0o711 too, so as to support userns-remapped containers. - if err := os.MkdirAll(d, 0711); err != nil { - return nil, err - } -diff --git a/plugins/cri/runtime/plugin.go b/plugins/cri/runtime/plugin.go -index adc64d9..07f64a1 100644 ---- a/plugins/cri/runtime/plugin.go -+++ b/plugins/cri/runtime/plugin.go -@@ -91,6 +91,13 @@ func initCRIRuntime(ic *plugin.InitContext) (interface{}, error) { - rootDir := filepath.Join(containerdRootDir, "io.containerd.grpc.v1.cri") - containerdStateDir := filepath.Dir(ic.Properties[plugins.PropertyStateDir]) - stateDir := filepath.Join(containerdStateDir, "io.containerd.grpc.v1.cri") -+ if err := os.MkdirAll(stateDir, 0o700); err != nil { -+ return nil, err -+ } -+ // chmod is needed for upgrading from an older release that created the dir with 0o755 -+ if err := os.Chmod(stateDir, 0o700); err != nil { -+ return nil, err -+ } - c := criconfig.Config{ - RuntimeConfig: *pluginConfig, - ContainerdRootDir: containerdRootDir, -diff --git a/plugins/sandbox/controller.go b/plugins/sandbox/controller.go -index aec9cc3..165f2e8 100644 ---- a/plugins/sandbox/controller.go -+++ b/plugins/sandbox/controller.go -@@ -68,7 +68,11 @@ func init() { - state := ic.Properties[plugins.PropertyStateDir] - root := ic.Properties[plugins.PropertyRootDir] - for _, d := range []string{root, state} { -- if err := os.MkdirAll(d, 0711); err != nil { -+ if err := os.MkdirAll(d, 0700); err != nil { -+ return nil, err -+ } -+ // chmod is needed for upgrading from an older release that created the dir with 0o711 -+ if err := os.Chmod(d, 0o700); err != nil { - return nil, err - } - } --- -2.45.4 - diff --git a/SPECS/containerd2/CVE-2024-40635.patch b/SPECS/containerd2/CVE-2024-40635.patch deleted file mode 100644 index a7604073e8a..00000000000 --- a/SPECS/containerd2/CVE-2024-40635.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 07a0b5419c408e70ed90179ea3e5825d986f80af Mon Sep 17 00:00:00 2001 -From: Craig Ingram -Date: Tue, 11 Mar 2025 14:52:44 +0000 -Subject: [PATCH] (cherry picked from commit - de1341c201ffb0effebbf51d00376181968c8779) - ---- - pkg/oci/spec_opts.go | 24 +++++++-- - pkg/oci/spec_opts_linux_test.go | 92 +++++++++++++++++++++++++++++++++ - 2 files changed, 112 insertions(+), 4 deletions(-) - -diff --git a/pkg/oci/spec_opts.go b/pkg/oci/spec_opts.go -index 3b85d764ae10..f7b298122957 100644 ---- a/pkg/oci/spec_opts.go -+++ b/pkg/oci/spec_opts.go -@@ -22,6 +22,7 @@ import ( - "encoding/json" - "errors" - "fmt" -+ "math" - "os" - "path/filepath" - "runtime" -@@ -593,6 +594,20 @@ func WithUser(userstr string) SpecOpts { - defer ensureAdditionalGids(s) - setProcess(s) - s.Process.User.AdditionalGids = nil -+ // While the Linux kernel allows the max UID to be MaxUint32 - 2, -+ // and the OCI Runtime Spec has no definition about the max UID, -+ // the runc implementation is known to require the UID to be <= MaxInt32. -+ // -+ // containerd follows runc's limitation here. -+ // -+ // In future we may relax this limitation to allow MaxUint32 - 2, -+ // or, amend the OCI Runtime Spec to codify the implementation limitation. -+ const ( -+ minUserID = 0 -+ maxUserID = math.MaxInt32 -+ minGroupID = 0 -+ maxGroupID = math.MaxInt32 -+ ) - - // For LCOW it's a bit harder to confirm that the user actually exists on the host as a rootfs isn't - // mounted on the host and shared into the guest, but rather the rootfs is constructed entirely in the -@@ -611,8 +626,8 @@ func WithUser(userstr string) SpecOpts { - switch len(parts) { - case 1: - v, err := strconv.Atoi(parts[0]) -- if err != nil { -- // if we cannot parse as a uint they try to see if it is a username -+ if err != nil || v < minUserID || v > maxUserID { -+ // if we cannot parse as an int32 then try to see if it is a username - return WithUsername(userstr)(ctx, client, c, s) - } - return WithUserID(uint32(v))(ctx, client, c, s) -@@ -623,12 +638,13 @@ func WithUser(userstr string) SpecOpts { - ) - var uid, gid uint32 - v, err := strconv.Atoi(parts[0]) -- if err != nil { -+ if err != nil || v < minUserID || v > maxUserID { - username = parts[0] - } else { - uid = uint32(v) - } -- if v, err = strconv.Atoi(parts[1]); err != nil { -+ v, err = strconv.Atoi(parts[1]) -+ if err != nil || v < minGroupID || v > maxGroupID { - groupname = parts[1] - } else { - gid = uint32(v) -diff --git a/pkg/oci/spec_opts_linux_test.go b/pkg/oci/spec_opts_linux_test.go -index 9299fa1807b6..d34af356b103 100644 ---- a/pkg/oci/spec_opts_linux_test.go -+++ b/pkg/oci/spec_opts_linux_test.go -@@ -33,6 +33,98 @@ import ( - "golang.org/x/sys/unix" - ) - -+//nolint:gosec -+func TestWithUser(t *testing.T) { -+ t.Parallel() -+ -+ expectedPasswd := `root:x:0:0:root:/root:/bin/ash -+guest:x:405:100:guest:/dev/null:/sbin/nologin -+` -+ expectedGroup := `root:x:0:root -+bin:x:1:root,bin,daemon -+daemon:x:2:root,bin,daemon -+sys:x:3:root,bin,adm -+guest:x:100:guest -+` -+ td := t.TempDir() -+ apply := fstest.Apply( -+ fstest.CreateDir("/etc", 0777), -+ fstest.CreateFile("/etc/passwd", []byte(expectedPasswd), 0777), -+ fstest.CreateFile("/etc/group", []byte(expectedGroup), 0777), -+ ) -+ if err := apply.Apply(td); err != nil { -+ t.Fatalf("failed to apply: %v", err) -+ } -+ c := containers.Container{ID: t.Name()} -+ testCases := []struct { -+ user string -+ expectedUID uint32 -+ expectedGID uint32 -+ err string -+ }{ -+ { -+ user: "0", -+ expectedUID: 0, -+ expectedGID: 0, -+ }, -+ { -+ user: "root:root", -+ expectedUID: 0, -+ expectedGID: 0, -+ }, -+ { -+ user: "guest", -+ expectedUID: 405, -+ expectedGID: 100, -+ }, -+ { -+ user: "guest:guest", -+ expectedUID: 405, -+ expectedGID: 100, -+ }, -+ { -+ user: "guest:nobody", -+ err: "no groups found", -+ }, -+ { -+ user: "405:100", -+ expectedUID: 405, -+ expectedGID: 100, -+ }, -+ { -+ user: "405:2147483648", -+ err: "no groups found", -+ }, -+ { -+ user: "-1000", -+ err: "no users found", -+ }, -+ { -+ user: "2147483648", -+ err: "no users found", -+ }, -+ } -+ for _, testCase := range testCases { -+ testCase := testCase -+ t.Run(testCase.user, func(t *testing.T) { -+ t.Parallel() -+ s := Spec{ -+ Version: specs.Version, -+ Root: &specs.Root{ -+ Path: td, -+ }, -+ Linux: &specs.Linux{}, -+ } -+ err := WithUser(testCase.user)(context.Background(), nil, &c, &s) -+ if err != nil { -+ assert.EqualError(t, err, testCase.err) -+ } -+ assert.Equal(t, testCase.expectedUID, s.Process.User.UID) -+ assert.Equal(t, testCase.expectedGID, s.Process.User.GID) -+ }) -+ } -+} -+ - //nolint:gosec - func TestWithUserID(t *testing.T) { - t.Parallel() diff --git a/SPECS/containerd2/CVE-2024-45338.patch b/SPECS/containerd2/CVE-2024-45338.patch deleted file mode 100644 index c2fb46031c5..00000000000 --- a/SPECS/containerd2/CVE-2024-45338.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 8e66b04771e35c4e4125e8c60334b34e2423effb Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Wed, 04 Dec 2024 09:35:55 -0800 -Subject: [PATCH] html: use strings.EqualFold instead of lowering ourselves - -Instead of using strings.ToLower and == to check case insensitive -equality, just use strings.EqualFold, even when the strings are only -ASCII. This prevents us unnecessarily lowering extremely long strings, -which can be a somewhat expensive operation, even if we're only -attempting to compare equality with five characters. - -Thanks to Guido Vranken for reporting this issue. - -Fixes golang/go#70906 -Fixes CVE-2024-45338 - -Change-Id: I323b919f912d60dab6a87cadfdcac3e6b54cd128 -Reviewed-on: https://go-review.googlesource.com/c/net/+/637536 -LUCI-TryBot-Result: Go LUCI -Auto-Submit: Gopher Robot -Reviewed-by: Roland Shoemaker -Reviewed-by: Tatiana Bradley ---- - vendor/golang.org/x/net/html/doctype.go | 2 +- - vendor/golang.org/x/net/html/foreign.go | 3 +-- - vendor/golang.org/x/net/html/parse.go | 4 ++-- - 3 files changed, 4 insertions(+), 5 deletions(-) - -diff --git a/vendor/golang.org/x/net/html/doctype.go b/vendor/golang.org/x/net/html/doctype.go -index c484e5a..bca3ae9 100644 ---- a/vendor/golang.org/x/net/html/doctype.go -+++ b/vendor/golang.org/x/net/html/doctype.go -@@ -87,7 +87,7 @@ func parseDoctype(s string) (n *Node, quirks bool) { - } - } - if lastAttr := n.Attr[len(n.Attr)-1]; lastAttr.Key == "system" && -- strings.ToLower(lastAttr.Val) == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd" { -+ strings.EqualFold(lastAttr.Val, "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd") { - quirks = true - } - } -diff --git a/vendor/golang.org/x/net/html/foreign.go b/vendor/golang.org/x/net/html/foreign.go -index 9da9e9d..e8515d8 100644 ---- a/vendor/golang.org/x/net/html/foreign.go -+++ b/vendor/golang.org/x/net/html/foreign.go -@@ -40,8 +40,7 @@ func htmlIntegrationPoint(n *Node) bool { - if n.Data == "annotation-xml" { - for _, a := range n.Attr { - if a.Key == "encoding" { -- val := strings.ToLower(a.Val) -- if val == "text/html" || val == "application/xhtml+xml" { -+ if strings.EqualFold(a.Val, "text/html") || strings.EqualFold(a.Val, "application/xhtml+xml") { - return true - } - } -diff --git a/vendor/golang.org/x/net/html/parse.go b/vendor/golang.org/x/net/html/parse.go -index 038941d..cb012d8 100644 ---- a/vendor/golang.org/x/net/html/parse.go -+++ b/vendor/golang.org/x/net/html/parse.go -@@ -1031,7 +1031,7 @@ func inBodyIM(p *parser) bool { - if p.tok.DataAtom == a.Input { - for _, t := range p.tok.Attr { - if t.Key == "type" { -- if strings.ToLower(t.Val) == "hidden" { -+ if strings.EqualFold(t.Val, "hidden") { - // Skip setting framesetOK = false - return true - } -@@ -1459,7 +1459,7 @@ func inTableIM(p *parser) bool { - return inHeadIM(p) - case a.Input: - for _, t := range p.tok.Attr { -- if t.Key == "type" && strings.ToLower(t.Val) == "hidden" { -+ if t.Key == "type" && strings.EqualFold(t.Val, "hidden") { - p.addElement() - p.oe.pop() - return true --- -2.25.1 - diff --git a/SPECS/containerd2/CVE-2025-22872.patch b/SPECS/containerd2/CVE-2025-22872.patch deleted file mode 100644 index c4c75f054fd..00000000000 --- a/SPECS/containerd2/CVE-2025-22872.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 072aace3657090fc2cd827741839d229aafd693e Mon Sep 17 00:00:00 2001 -From: Aninda -Date: Thu, 22 May 2025 10:01:10 -0400 -Subject: [PATCH] Address CVE-2025-22872 -Upstream Patch Reference: https://github.com/golang/net/commit/e1fcd82abba34df74614020343be8eb1fe85f0d9 - ---- - vendor/golang.org/x/net/html/token.go | 18 ++++++++++++++++-- - 1 file changed, 16 insertions(+), 2 deletions(-) - -diff --git a/vendor/golang.org/x/net/html/token.go b/vendor/golang.org/x/net/html/token.go -index 3c57880..6598c1f 100644 ---- a/vendor/golang.org/x/net/html/token.go -+++ b/vendor/golang.org/x/net/html/token.go -@@ -839,8 +839,22 @@ func (z *Tokenizer) readStartTag() TokenType { - if raw { - z.rawTag = strings.ToLower(string(z.buf[z.data.start:z.data.end])) - } -- // Look for a self-closing token like "
". -- if z.err == nil && z.buf[z.raw.end-2] == '/' { -+ // Look for a self-closing token (e.g.
). -+ // -+ // Originally, we did this by just checking that the last character of the -+ // tag (ignoring the closing bracket) was a solidus (/) character, but this -+ // is not always accurate. -+ // -+ // We need to be careful that we don't misinterpret a non-self-closing tag -+ // as self-closing, as can happen if the tag contains unquoted attribute -+ // values (i.e.

). -+ // -+ // To avoid this, we check that the last non-bracket character of the tag -+ // (z.raw.end-2) isn't the same character as the last non-quote character of -+ // the last attribute of the tag (z.pendingAttr[1].end-1), if the tag has -+ // attributes. -+ nAttrs := len(z.attr) -+ if z.err == nil && z.buf[z.raw.end-2] == '/' && (nAttrs == 0 || z.raw.end-2 != z.attr[nAttrs-1][1].end-1) { - return SelfClosingTagToken - } - return StartTagToken --- -2.34.1 - diff --git a/SPECS/containerd2/CVE-2025-27144.patch b/SPECS/containerd2/CVE-2025-27144.patch deleted file mode 100644 index 734158a6a89..00000000000 --- a/SPECS/containerd2/CVE-2025-27144.patch +++ /dev/null @@ -1,49 +0,0 @@ -From fa324fa38481f9d2da9109cb5983326f62ff7507 Mon Sep 17 00:00:00 2001 -From: Kanishk-Bansal -Date: Fri, 28 Feb 2025 07:45:53 +0000 -Subject: [PATCH] CVE-2025-27144 -Upstream Ref: https://github.com/go-jose/go-jose/commit/c9ed84d8f0cfadcfad817150158caca6fcbc518b - ---- - vendor/github.com/go-jose/go-jose/v4/jwe.go | 5 +++-- - vendor/github.com/go-jose/go-jose/v4/jws.go | 5 +++-- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/vendor/github.com/go-jose/go-jose/v4/jwe.go b/vendor/github.com/go-jose/go-jose/v4/jwe.go -index 89f03ee..9f1322d 100644 ---- a/vendor/github.com/go-jose/go-jose/v4/jwe.go -+++ b/vendor/github.com/go-jose/go-jose/v4/jwe.go -@@ -288,10 +288,11 @@ func ParseEncryptedCompact( - keyAlgorithms []KeyAlgorithm, - contentEncryption []ContentEncryption, - ) (*JSONWebEncryption, error) { -- parts := strings.Split(input, ".") -- if len(parts) != 5 { -+ // Five parts is four separators -+ if strings.Count(input, ".") != 4 { - return nil, fmt.Errorf("go-jose/go-jose: compact JWE format must have five parts") - } -+ parts := strings.SplitN(input, ".", 5) - - rawProtected, err := base64.RawURLEncoding.DecodeString(parts[0]) - if err != nil { -diff --git a/vendor/github.com/go-jose/go-jose/v4/jws.go b/vendor/github.com/go-jose/go-jose/v4/jws.go -index 3a91230..d09d8ba 100644 ---- a/vendor/github.com/go-jose/go-jose/v4/jws.go -+++ b/vendor/github.com/go-jose/go-jose/v4/jws.go -@@ -327,10 +327,11 @@ func parseSignedCompact( - payload []byte, - signatureAlgorithms []SignatureAlgorithm, - ) (*JSONWebSignature, error) { -- parts := strings.Split(input, ".") -- if len(parts) != 3 { -+ // Three parts is two separators -+ if strings.Count(input, ".") != 2 { - return nil, fmt.Errorf("go-jose/go-jose: compact JWS format must have three parts") - } -+ parts := strings.SplitN(input, ".", 3) - - if parts[1] != "" && payload != nil { - return nil, fmt.Errorf("go-jose/go-jose: payload is not detached") --- -2.34.1 diff --git a/SPECS/containerd2/CVE-2025-47291.patch b/SPECS/containerd2/CVE-2025-47291.patch deleted file mode 100644 index 5393e181fb1..00000000000 --- a/SPECS/containerd2/CVE-2025-47291.patch +++ /dev/null @@ -1,220 +0,0 @@ -From 0bb95c53ec07aad729470844c8f0e5ab2838a8db Mon Sep 17 00:00:00 2001 -From: dj_palli -Date: Mon, 2 Jun 2025 14:45:30 +0000 -Subject: [PATCH] Address CVE-2025-47291 - -Upstream patch URL : https://github.com/containerd/containerd/commit/ec3567d6b369cde39739b41db8763a19d6f35c39 - ---- - client/container.go | 3 ++- - client/task.go | 27 ++++++++++++++++++++++ - client/task_opts.go | 27 ++++++++-------------- - client/task_opts_unix.go | 48 +++++++++++++--------------------------- - 4 files changed, 53 insertions(+), 52 deletions(-) - -diff --git a/client/container.go b/client/container.go -index b9cf25e..5763ae6 100644 ---- a/client/container.go -+++ b/client/container.go -@@ -279,7 +279,8 @@ func (c *container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...N - } - } - info := TaskInfo{ -- runtime: r.Runtime.Name, -+ runtime: r.Runtime.Name, -+ runtimeOptions: r.Runtime.Options, - } - for _, o := range opts { - if err := o(ctx, c.client, &info); err != nil { -diff --git a/client/task.go b/client/task.go -index 20312a9..152babe 100644 ---- a/client/task.go -+++ b/client/task.go -@@ -146,6 +146,10 @@ type TaskInfo struct { - - // runtime is the runtime name for the container, and cannot be changed. - runtime string -+ // runtimeOptions is the runtime options for the container, and when task options are set, -+ // they will be based on the runtimeOptions. -+ // https://github.com/containerd/containerd/issues/11568 -+ runtimeOptions typeurl.Any - } - - // Runtime name for the container -@@ -153,6 +157,29 @@ func (i *TaskInfo) Runtime() string { - return i.runtime - } - -+// getRuncOptions returns a reference to the runtime options for use by the task. -+// If the set of options is not set by the opts passed into the NewTask creation -+// this function first attempts to initialize the runtime options with a copy of the runtimeOptions, -+// otherwise an empty set of options is assigned and returned -+func (i *TaskInfo) getRuncOptions() (*options.Options, error) { -+ if i.Options != nil { -+ opts, ok := i.Options.(*options.Options) -+ if !ok { -+ return nil, errors.New("invalid runtime v2 options format") -+ } -+ return opts, nil -+ } -+ -+ opts := &options.Options{} -+ if i.runtimeOptions != nil && i.runtimeOptions.GetValue() != nil { -+ if err := typeurl.UnmarshalTo(i.runtimeOptions, opts); err != nil { -+ return nil, fmt.Errorf("failed to get runtime v2 options: %w", err) -+ } -+ } -+ i.Options = opts -+ return opts, nil -+} -+ - // Task is the executable object within containerd - type Task interface { - Process -diff --git a/client/task_opts.go b/client/task_opts.go -index 8e94d4c..27bde35 100644 ---- a/client/task_opts.go -+++ b/client/task_opts.go -@@ -54,12 +54,9 @@ func WithRuntimePath(absRuntimePath string) NewTaskOpts { - // usually it is served inside a sandbox, and we can get it from sandbox status. - func WithTaskAPIEndpoint(address string, version uint32) NewTaskOpts { - return func(ctx context.Context, client *Client, info *TaskInfo) error { -- if info.Options == nil { -- info.Options = &options.Options{} -- } -- opts, ok := info.Options.(*options.Options) -- if !ok { -- return errors.New("invalid runtime v2 options format") -+ opts, err := info.getRuncOptions() -+ if err != nil { -+ return err - } - opts.TaskApiAddress = address - opts.TaskApiVersion = version -@@ -119,12 +116,9 @@ func WithCheckpointImagePath(path string) CheckpointTaskOpts { - // WithRestoreImagePath sets image path for create option - func WithRestoreImagePath(path string) NewTaskOpts { - return func(ctx context.Context, c *Client, ti *TaskInfo) error { -- if ti.Options == nil { -- ti.Options = &options.Options{} -- } -- opts, ok := ti.Options.(*options.Options) -- if !ok { -- return errors.New("invalid runtime v2 options format") -+ opts, err := ti.getRuncOptions() -+ if err != nil { -+ return err - } - opts.CriuImagePath = path - return nil -@@ -134,12 +128,9 @@ func WithRestoreImagePath(path string) NewTaskOpts { - // WithRestoreWorkPath sets criu work path for create option - func WithRestoreWorkPath(path string) NewTaskOpts { - return func(ctx context.Context, c *Client, ti *TaskInfo) error { -- if ti.Options == nil { -- ti.Options = &options.Options{} -- } -- opts, ok := ti.Options.(*options.Options) -- if !ok { -- return errors.New("invalid runtime v2 options format") -+ opts, err := ti.getRuncOptions() -+ if err != nil { -+ return err - } - opts.CriuWorkPath = path - return nil -diff --git a/client/task_opts_unix.go b/client/task_opts_unix.go -index d33e302..26b5c17 100644 ---- a/client/task_opts_unix.go -+++ b/client/task_opts_unix.go -@@ -20,20 +20,14 @@ package client - - import ( - "context" -- "errors" -- -- "github.com/containerd/containerd/api/types/runc/options" - ) - - // WithNoNewKeyring causes tasks not to be created with a new keyring for secret storage. - // There is an upper limit on the number of keyrings in a linux system - func WithNoNewKeyring(ctx context.Context, c *Client, ti *TaskInfo) error { -- if ti.Options == nil { -- ti.Options = &options.Options{} -- } -- opts, ok := ti.Options.(*options.Options) -- if !ok { -- return errors.New("invalid v2 shim create options format") -+ opts, err := ti.getRuncOptions() -+ if err != nil { -+ return err - } - opts.NoNewKeyring = true - return nil -@@ -41,12 +35,9 @@ func WithNoNewKeyring(ctx context.Context, c *Client, ti *TaskInfo) error { - - // WithNoPivotRoot instructs the runtime not to you pivot_root - func WithNoPivotRoot(_ context.Context, _ *Client, ti *TaskInfo) error { -- if ti.Options == nil { -- ti.Options = &options.Options{} -- } -- opts, ok := ti.Options.(*options.Options) -- if !ok { -- return errors.New("invalid v2 shim create options format") -+ opts, err := ti.getRuncOptions() -+ if err != nil { -+ return err - } - opts.NoPivotRoot = true - return nil -@@ -55,12 +46,9 @@ func WithNoPivotRoot(_ context.Context, _ *Client, ti *TaskInfo) error { - // WithShimCgroup sets the existing cgroup for the shim - func WithShimCgroup(path string) NewTaskOpts { - return func(ctx context.Context, c *Client, ti *TaskInfo) error { -- if ti.Options == nil { -- ti.Options = &options.Options{} -- } -- opts, ok := ti.Options.(*options.Options) -- if !ok { -- return errors.New("invalid v2 shim create options format") -+ opts, err := ti.getRuncOptions() -+ if err != nil { -+ return err - } - opts.ShimCgroup = path - return nil -@@ -70,12 +58,9 @@ func WithShimCgroup(path string) NewTaskOpts { - // WithUIDOwner allows console I/O to work with the remapped UID in user namespace - func WithUIDOwner(uid uint32) NewTaskOpts { - return func(ctx context.Context, c *Client, ti *TaskInfo) error { -- if ti.Options == nil { -- ti.Options = &options.Options{} -- } -- opts, ok := ti.Options.(*options.Options) -- if !ok { -- return errors.New("invalid v2 shim create options format") -+ opts, err := ti.getRuncOptions() -+ if err != nil { -+ return err - } - opts.IoUid = uid - return nil -@@ -85,12 +70,9 @@ func WithUIDOwner(uid uint32) NewTaskOpts { - // WithGIDOwner allows console I/O to work with the remapped GID in user namespace - func WithGIDOwner(gid uint32) NewTaskOpts { - return func(ctx context.Context, c *Client, ti *TaskInfo) error { -- if ti.Options == nil { -- ti.Options = &options.Options{} -- } -- opts, ok := ti.Options.(*options.Options) -- if !ok { -- return errors.New("invalid v2 shim create options format") -+ opts, err := ti.getRuncOptions() -+ if err != nil { -+ return err - } - opts.IoGid = gid - return nil --- -2.45.2 - diff --git a/SPECS/containerd2/CVE-2025-47911.patch b/SPECS/containerd2/CVE-2025-47911.patch deleted file mode 100644 index 2df8cafa55b..00000000000 --- a/SPECS/containerd2/CVE-2025-47911.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 532532d877df8bbee095441886578acaf619132c Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Mon, 29 Sep 2025 16:33:18 -0700 -Subject: [PATCH] html: impose open element stack size limit - -The HTML specification contains a number of algorithms which are -quadratic in complexity by design. Instead of adding complicated -workarounds to prevent these cases from becoming extremely expensive in -pathological cases, we impose a limit of 512 to the size of the stack of -open elements. It is extremely unlikely that non-adversarial HTML -documents will ever hit this limit (but if we see cases of this, we may -want to make the limit configurable via a ParseOption). - -Thanks to Guido Vranken and Jakub Ciolek for both independently -reporting this issue. - -Fixes CVE-2025-47911 -Fixes golang/go#75682 - -Change-Id: I890517b189af4ffbf427d25d3fde7ad7ec3509ad -Reviewed-on: https://go-review.googlesource.com/c/net/+/709876 -Reviewed-by: Damien Neil -LUCI-TryBot-Result: Go LUCI -Signed-off-by: Azure Linux Security Servicing Account -Upstream-reference: https://github.com/golang/net/commit/59706cdaa8f95502fdec64b67b4c61d6ca58727d.patch ---- - vendor/golang.org/x/net/html/escape.go | 2 +- - vendor/golang.org/x/net/html/parse.go | 21 +++++++++++++++++---- - 2 files changed, 18 insertions(+), 5 deletions(-) - -diff --git a/vendor/golang.org/x/net/html/escape.go b/vendor/golang.org/x/net/html/escape.go -index 04c6bec..12f2273 100644 ---- a/vendor/golang.org/x/net/html/escape.go -+++ b/vendor/golang.org/x/net/html/escape.go -@@ -299,7 +299,7 @@ func escape(w writer, s string) error { - case '\r': - esc = " " - default: -- panic("unrecognized escape character") -+ panic("html: unrecognized escape character") - } - s = s[i+1:] - if _, err := w.WriteString(esc); err != nil { -diff --git a/vendor/golang.org/x/net/html/parse.go b/vendor/golang.org/x/net/html/parse.go -index 979ef17..4d12a1c 100644 ---- a/vendor/golang.org/x/net/html/parse.go -+++ b/vendor/golang.org/x/net/html/parse.go -@@ -231,7 +231,14 @@ func (p *parser) addChild(n *Node) { - } - - if n.Type == ElementNode { -- p.oe = append(p.oe, n) -+ p.insertOpenElement(n) -+ } -+} -+ -+func (p *parser) insertOpenElement(n *Node) { -+ p.oe = append(p.oe, n) -+ if len(p.oe) > 512 { -+ panic("html: open stack of elements exceeds 512 nodes") - } - } - -@@ -810,7 +817,7 @@ func afterHeadIM(p *parser) bool { - p.im = inFramesetIM - return true - case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title: -- p.oe = append(p.oe, p.head) -+ p.insertOpenElement(p.head) - defer p.oe.remove(p.head) - return inHeadIM(p) - case a.Head: -@@ -2320,9 +2327,13 @@ func (p *parser) parseCurrentToken() { - } - } - --func (p *parser) parse() error { -+func (p *parser) parse() (err error) { -+ defer func() { -+ if panicErr := recover(); panicErr != nil { -+ err = fmt.Errorf("%s", panicErr) -+ } -+ }() - // Iterate until EOF. Any other error will cause an early return. -- var err error - for err != io.EOF { - // CDATA sections are allowed only in foreign content. - n := p.oe.top() -@@ -2351,6 +2362,8 @@ func (p *parser) parse() error { - // s. Conversely, explicit s in r's data can be silently dropped, - // with no corresponding node in the resulting tree. - // -+// Parse will reject HTML that is nested deeper than 512 elements. -+// - // The input is assumed to be UTF-8 encoded. - func Parse(r io.Reader) (*Node, error) { - return ParseWithOptions(r) --- -2.45.4 - diff --git a/SPECS/containerd2/CVE-2025-58190.patch b/SPECS/containerd2/CVE-2025-58190.patch deleted file mode 100644 index 89b2b84a029..00000000000 --- a/SPECS/containerd2/CVE-2025-58190.patch +++ /dev/null @@ -1,126 +0,0 @@ -From 582919df8cf0643cd434da7421238628ad5b4cb6 Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Mon, 29 Sep 2025 19:38:24 -0700 -Subject: [PATCH] html: align in row insertion mode with spec - -Update inRowIM to match the HTML specification. This fixes an issue -where a specific HTML document could cause the parser to enter an -infinite loop when trying to parse a and implied next to -each other. - -Fixes CVE-2025-58190 -Fixes golang/go#70179 - -Change-Id: Idcb133c87c7d475cc8c7eb1f1550ea21d8bdddea -Reviewed-on: https://go-review.googlesource.com/c/net/+/709875 -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Damien Neil -Signed-off-by: Azure Linux Security Servicing Account -Upstream-reference: https://github.com/golang/net/commit/6ec8895aa5f6594da7356da7d341b98133629009.patch ---- - vendor/golang.org/x/net/html/parse.go | 36 ++++++++++++++++++--------- - 1 file changed, 24 insertions(+), 12 deletions(-) - -diff --git a/vendor/golang.org/x/net/html/parse.go b/vendor/golang.org/x/net/html/parse.go -index 5b8374b..979ef17 100644 ---- a/vendor/golang.org/x/net/html/parse.go -+++ b/vendor/golang.org/x/net/html/parse.go -@@ -136,7 +136,7 @@ func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int { - return -1 - } - default: -- panic("unreachable") -+ panic(fmt.Sprintf("html: internal error: indexOfElementInScope unknown scope: %d", s)) - } - } - switch s { -@@ -179,7 +179,7 @@ func (p *parser) clearStackToContext(s scope) { - return - } - default: -- panic("unreachable") -+ panic(fmt.Sprintf("html: internal error: clearStackToContext unknown scope: %d", s)) - } - } - } -@@ -1674,7 +1674,7 @@ func inTableBodyIM(p *parser) bool { - return inTableIM(p) - } - --// Section 12.2.6.4.14. -+// Section 13.2.6.4.14. - func inRowIM(p *parser) bool { - switch p.tok.Type { - case StartTagToken: -@@ -1686,7 +1686,9 @@ func inRowIM(p *parser) bool { - p.im = inCellIM - return true - case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead, a.Tr: -- if p.popUntil(tableScope, a.Tr) { -+ if p.elementInScope(tableScope, a.Tr) { -+ p.clearStackToContext(tableRowScope) -+ p.oe.pop() - p.im = inTableBodyIM - return false - } -@@ -1696,22 +1698,28 @@ func inRowIM(p *parser) bool { - case EndTagToken: - switch p.tok.DataAtom { - case a.Tr: -- if p.popUntil(tableScope, a.Tr) { -+ if p.elementInScope(tableScope, a.Tr) { -+ p.clearStackToContext(tableRowScope) -+ p.oe.pop() - p.im = inTableBodyIM - return true - } - // Ignore the token. - return true - case a.Table: -- if p.popUntil(tableScope, a.Tr) { -+ if p.elementInScope(tableScope, a.Tr) { -+ p.clearStackToContext(tableRowScope) -+ p.oe.pop() - p.im = inTableBodyIM - return false - } - // Ignore the token. - return true - case a.Tbody, a.Tfoot, a.Thead: -- if p.elementInScope(tableScope, p.tok.DataAtom) { -- p.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String()) -+ if p.elementInScope(tableScope, p.tok.DataAtom) && p.elementInScope(tableScope, a.Tr) { -+ p.clearStackToContext(tableRowScope) -+ p.oe.pop() -+ p.im = inTableBodyIM - return false - } - // Ignore the token. -@@ -2218,16 +2226,20 @@ func parseForeignContent(p *parser) bool { - p.acknowledgeSelfClosingTag() - } - case EndTagToken: -+ if strings.EqualFold(p.oe[len(p.oe)-1].Data, p.tok.Data) { -+ p.oe = p.oe[:len(p.oe)-1] -+ return true -+ } - for i := len(p.oe) - 1; i >= 0; i-- { -- if p.oe[i].Namespace == "" { -- return p.im(p) -- } - if strings.EqualFold(p.oe[i].Data, p.tok.Data) { - p.oe = p.oe[:i] -+ return true -+ } -+ if i > 0 && p.oe[i-1].Namespace == "" { - break - } - } -- return true -+ return p.im(p) - default: - // Ignore the token. - } --- -2.45.4 - diff --git a/SPECS/containerd2/CVE-2025-64329.patch b/SPECS/containerd2/CVE-2025-64329.patch deleted file mode 100644 index b742c82c321..00000000000 --- a/SPECS/containerd2/CVE-2025-64329.patch +++ /dev/null @@ -1,73 +0,0 @@ -From b9beeef78a6fd90ece5801780c45f550caf71b3d Mon Sep 17 00:00:00 2001 -From: wheat2018 <1151937289@qq.com> -Date: Tue, 13 Aug 2024 15:56:31 +0800 -Subject: [PATCH] fix goroutine leak of container Attach - -The monitor goroutine (runs (*ContainerIO).Attach.func1) of Attach will -never finish if it attaches to a container without any stdout or stderr -output. Wait for http context cancel and break the pipe actively to -address the issue. - -Signed-off-by: wheat2018 <1151937289@qq.com> -Signed-off-by: Akihiro Suda -Signed-off-by: Azure Linux Security Servicing Account -Upstream-reference: https://github.com/containerd/containerd/commit/083b53cd6f19b5de7717b0ce92c11bdf95e612df.patch ---- - internal/cri/io/container_io.go | 14 +++++++++++--- - internal/cri/server/container_attach.go | 2 +- - 2 files changed, 12 insertions(+), 4 deletions(-) - -diff --git a/internal/cri/io/container_io.go b/internal/cri/io/container_io.go -index 9fc5545..194634e 100644 ---- a/internal/cri/io/container_io.go -+++ b/internal/cri/io/container_io.go -@@ -17,6 +17,7 @@ - package io - - import ( -+ "context" - "errors" - "fmt" - "io" -@@ -160,7 +161,7 @@ func (c *ContainerIO) Pipe() { - - // Attach attaches container stdio. - // TODO(random-liu): Use pools.Copy in docker to reduce memory usage? --func (c *ContainerIO) Attach(opts AttachOptions) { -+func (c *ContainerIO) Attach(ctx context.Context, opts AttachOptions) { - var wg sync.WaitGroup - key := util.GenerateID() - stdinKey := streamKey(c.id, "attach-"+key, Stdin) -@@ -201,8 +202,15 @@ func (c *ContainerIO) Attach(opts AttachOptions) { - } - - attachStream := func(key string, close <-chan struct{}) { -- <-close -- log.L.Infof("Attach stream %q closed", key) -+ select { -+ case <-close: -+ log.L.Infof("Attach stream %q closed", key) -+ case <-ctx.Done(): -+ log.L.Infof("Attach client of %q cancelled", key) -+ // Avoid writeGroup heap up -+ c.stdoutGroup.Remove(key) -+ c.stderrGroup.Remove(key) -+ } - // Make sure stdin gets closed. - if stdinStreamRC != nil { - stdinStreamRC.Close() -diff --git a/internal/cri/server/container_attach.go b/internal/cri/server/container_attach.go -index 0147859..f4c3322 100644 ---- a/internal/cri/server/container_attach.go -+++ b/internal/cri/server/container_attach.go -@@ -82,6 +82,6 @@ func (c *criService) attachContainer(ctx context.Context, id string, stdin io.Re - }, - } - // TODO(random-liu): Figure out whether we need to support historical output. -- cntr.IO.Attach(opts) -+ cntr.IO.Attach(ctx, opts) - return nil - } --- -2.45.4 - diff --git a/SPECS/containerd2/CVE-2026-35469.patch b/SPECS/containerd2/CVE-2026-35469.patch deleted file mode 100644 index e13ad1dc20d..00000000000 --- a/SPECS/containerd2/CVE-2026-35469.patch +++ /dev/null @@ -1,727 +0,0 @@ -From a3c65cb3e57e41d3961862bb680b2ba5e499f81a Mon Sep 17 00:00:00 2001 -From: Kanishk Bansal -Date: Wed, 8 Apr 2026 08:52:21 +0000 -Subject: [PATCH 1/3] Upgrade moby/spdystream v0.5.0 - -Signed-off-by: Kanishk Bansal ---- - go.mod | 2 +- - go.sum | 4 ++-- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/go.mod b/go.mod -index 9717218..185be98 100644 ---- a/go.mod -+++ b/go.mod -@@ -113,7 +113,7 @@ require ( - github.com/mdlayher/socket v0.4.1 // indirect - github.com/miekg/pkcs11 v1.1.1 // indirect - github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect -- github.com/moby/spdystream v0.4.0 // indirect -+ github.com/moby/spdystream v0.5.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect -diff --git a/go.sum b/go.sum -index a52345b..3b7dcf9 100644 ---- a/go.sum -+++ b/go.sum -@@ -982,8 +982,8 @@ github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkO - github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs= - github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= - github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= --github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= --github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= -+github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= -+github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= - github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= - github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= - github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= --- -2.45.4 - - -From 0b29f4cf6ec37c149b39d5340c6c9d10a4f311ec Mon Sep 17 00:00:00 2001 -From: Kanishk Bansal -Date: Wed, 8 Apr 2026 08:56:07 +0000 -Subject: [PATCH 2/3] Code Upgrade github.com/moby/spdystream to v0.5.0 - -Signed-off-by: Kanishk Bansal ---- - .../github.com/moby/spdystream/connection.go | 18 +++++++++++++++--- - vendor/modules.txt | 2 +- - 2 files changed, 16 insertions(+), 4 deletions(-) - -diff --git a/vendor/github.com/moby/spdystream/connection.go b/vendor/github.com/moby/spdystream/connection.go -index d649ecc..1394d0a 100644 ---- a/vendor/github.com/moby/spdystream/connection.go -+++ b/vendor/github.com/moby/spdystream/connection.go -@@ -712,7 +712,9 @@ func (s *Connection) shutdown(closeTimeout time.Duration) { - - var timeout <-chan time.Time - if closeTimeout > time.Duration(0) { -- timeout = time.After(closeTimeout) -+ timer := time.NewTimer(closeTimeout) -+ defer timer.Stop() -+ timeout = timer.C - } - streamsClosed := make(chan bool) - -@@ -739,7 +741,15 @@ func (s *Connection) shutdown(closeTimeout time.Duration) { - } - - if err != nil { -- duration := 10 * time.Minute -+ // default to 1 second -+ duration := time.Second -+ // if a closeTimeout was given, use that, clipped to 1s-10m -+ if closeTimeout > time.Second { -+ duration = closeTimeout -+ } -+ if duration > 10*time.Minute { -+ duration = 10 * time.Minute -+ } - timer := time.NewTimer(duration) - defer timer.Stop() - select { -@@ -806,7 +816,9 @@ func (s *Connection) CloseWait() error { - func (s *Connection) Wait(waitTimeout time.Duration) error { - var timeout <-chan time.Time - if waitTimeout > time.Duration(0) { -- timeout = time.After(waitTimeout) -+ timer := time.NewTimer(waitTimeout) -+ defer timer.Stop() -+ timeout = timer.C - } - - select { -diff --git a/vendor/modules.txt b/vendor/modules.txt -index b22f7d2..bee6257 100644 ---- a/vendor/modules.txt -+++ b/vendor/modules.txt -@@ -359,7 +359,7 @@ github.com/mistifyio/go-zfs/v3 - # github.com/moby/locker v1.0.1 - ## explicit; go 1.13 - github.com/moby/locker --# github.com/moby/spdystream v0.4.0 -+# github.com/moby/spdystream v0.5.0 - ## explicit; go 1.13 - github.com/moby/spdystream - github.com/moby/spdystream/spdy --- -2.45.4 - - -From 47557d76f7795ba4d14ff30c548a1bb7abf03126 Mon Sep 17 00:00:00 2001 -From: Kanishk Bansal -Date: Mon, 13 Apr 2026 18:46:44 +0000 -Subject: [PATCH 3/3] CVE-2026-35469 - -Signed-off-by: Kanishk Bansal ---- - vendor/github.com/moby/spdystream/NOTICE | 12 +++ - .../github.com/moby/spdystream/connection.go | 11 ++- - .../github.com/moby/spdystream/spdy/LICENSE | 27 +++++++ - .../github.com/moby/spdystream/spdy/PATENTS | 22 +++++ - .../moby/spdystream/spdy/dictionary.go | 16 ---- - .../moby/spdystream/spdy/options.go | 25 ++++++ - .../moby/spdystream/spdy/options_test.go | 33 ++++++++ - .../github.com/moby/spdystream/spdy/read.go | 58 ++++++++----- - .../github.com/moby/spdystream/spdy/types.go | 49 +++++++---- - .../github.com/moby/spdystream/spdy/write.go | 81 ++++++++++++------- - 10 files changed, 251 insertions(+), 83 deletions(-) - create mode 100644 vendor/github.com/moby/spdystream/spdy/LICENSE - create mode 100644 vendor/github.com/moby/spdystream/spdy/PATENTS - create mode 100644 vendor/github.com/moby/spdystream/spdy/options.go - create mode 100644 vendor/github.com/moby/spdystream/spdy/options_test.go - -diff --git a/vendor/github.com/moby/spdystream/NOTICE b/vendor/github.com/moby/spdystream/NOTICE -index b9b11c9..24e2e2a 100644 ---- a/vendor/github.com/moby/spdystream/NOTICE -+++ b/vendor/github.com/moby/spdystream/NOTICE -@@ -3,3 +3,15 @@ Copyright 2014-2021 Docker Inc. - - This product includes software developed at - Docker Inc. (https://www.docker.com/). -+ -+SPDY implementation (spdy/) -+ -+The spdy directory contains code derived from the Go project (golang.org/x/net). -+ -+Copyright 2009-2013 The Go Authors. -+Licensed under the BSD 3-Clause License. -+ -+Modifications Copyright 2014-2021 Docker Inc. -+ -+The BSD license text and Go patent grant are included in -+spdy/LICENSE and spdy/PATENTS. -diff --git a/vendor/github.com/moby/spdystream/connection.go b/vendor/github.com/moby/spdystream/connection.go -index 1394d0a..69ce477 100644 ---- a/vendor/github.com/moby/spdystream/connection.go -+++ b/vendor/github.com/moby/spdystream/connection.go -@@ -224,7 +224,13 @@ type Connection struct { - // NewConnection creates a new spdy connection from an existing - // network connection. - func NewConnection(conn net.Conn, server bool) (*Connection, error) { -- framer, framerErr := spdy.NewFramer(conn, conn) -+ return NewConnectionWithOptions(conn, server) -+} -+ -+// NewConnectionWithOptions creates a new spdy connection and applies frame -+// parsing limits via options. -+func NewConnectionWithOptions(conn net.Conn, server bool, opts ...spdy.FramerOption) (*Connection, error) { -+ framer, framerErr := spdy.NewFramerWithOptions(conn, conn, opts...) - if framerErr != nil { - return nil, framerErr - } -@@ -350,6 +356,9 @@ Loop: - } else { - debugMessage("(%p) EOF received", s) - } -+ if spdyErr, ok := err.(*spdy.Error); ok && spdyErr.Err == spdy.InvalidControlFrame { -+ _ = s.conn.Close() -+ } - break - } - var priority uint8 -diff --git a/vendor/github.com/moby/spdystream/spdy/LICENSE b/vendor/github.com/moby/spdystream/spdy/LICENSE -new file mode 100644 -index 0000000..6a66aea ---- /dev/null -+++ b/vendor/github.com/moby/spdystream/spdy/LICENSE -@@ -0,0 +1,27 @@ -+Copyright (c) 2009 The Go Authors. All rights reserved. -+ -+Redistribution and use in source and binary forms, with or without -+modification, are permitted provided that the following conditions are -+met: -+ -+ * Redistributions of source code must retain the above copyright -+notice, this list of conditions and the following disclaimer. -+ * Redistributions in binary form must reproduce the above -+copyright notice, this list of conditions and the following disclaimer -+in the documentation and/or other materials provided with the -+distribution. -+ * Neither the name of Google Inc. nor the names of its -+contributors may be used to endorse or promote products derived from -+this software without specific prior written permission. -+ -+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -diff --git a/vendor/github.com/moby/spdystream/spdy/PATENTS b/vendor/github.com/moby/spdystream/spdy/PATENTS -new file mode 100644 -index 0000000..7330990 ---- /dev/null -+++ b/vendor/github.com/moby/spdystream/spdy/PATENTS -@@ -0,0 +1,22 @@ -+Additional IP Rights Grant (Patents) -+ -+"This implementation" means the copyrightable works distributed by -+Google as part of the Go project. -+ -+Google hereby grants to You a perpetual, worldwide, non-exclusive, -+no-charge, royalty-free, irrevocable (except as stated in this section) -+patent license to make, have made, use, offer to sell, sell, import, -+transfer and otherwise run, modify and propagate the contents of this -+implementation of Go, where such license applies only to those patent -+claims, both currently owned or controlled by Google and acquired in -+the future, licensable by Google that are necessarily infringed by this -+implementation of Go. This grant does not include claims that would be -+infringed only as a consequence of further modification of this -+implementation. If you or your agent or exclusive licensee institute or -+order or agree to the institution of patent litigation against any -+entity (including a cross-claim or counterclaim in a lawsuit) alleging -+that this implementation of Go or any code incorporated within this -+implementation of Go constitutes direct or contributory patent -+infringement, or inducement of patent infringement, then any patent -+rights granted to you under this License for this implementation of Go -+shall terminate as of the date such litigation is filed. -diff --git a/vendor/github.com/moby/spdystream/spdy/dictionary.go b/vendor/github.com/moby/spdystream/spdy/dictionary.go -index 392232f..5a5ff0e 100644 ---- a/vendor/github.com/moby/spdystream/spdy/dictionary.go -+++ b/vendor/github.com/moby/spdystream/spdy/dictionary.go -@@ -1,19 +1,3 @@ --/* -- Copyright 2014-2021 Docker Inc. -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. --*/ -- - // Copyright 2013 The Go Authors. All rights reserved. - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -diff --git a/vendor/github.com/moby/spdystream/spdy/options.go b/vendor/github.com/moby/spdystream/spdy/options.go -new file mode 100644 -index 0000000..ec03e0b ---- /dev/null -+++ b/vendor/github.com/moby/spdystream/spdy/options.go -@@ -0,0 +1,25 @@ -+package spdy -+ -+// FramerOption allows callers to customize frame parsing limits. -+type FramerOption func(*Framer) -+ -+// WithMaxControlFramePayloadSize sets the control-frame payload limit. -+func WithMaxControlFramePayloadSize(size uint32) FramerOption { -+ return func(f *Framer) { -+ f.maxFrameLength = size -+ } -+} -+ -+// WithMaxHeaderFieldSize sets the per-header name/value size limit. -+func WithMaxHeaderFieldSize(size uint32) FramerOption { -+ return func(f *Framer) { -+ f.maxHeaderFieldSize = size -+ } -+} -+ -+// WithMaxHeaderCount sets the maximum number of headers in a frame. -+func WithMaxHeaderCount(count uint32) FramerOption { -+ return func(f *Framer) { -+ f.maxHeaderCount = count -+ } -+} -diff --git a/vendor/github.com/moby/spdystream/spdy/options_test.go b/vendor/github.com/moby/spdystream/spdy/options_test.go -new file mode 100644 -index 0000000..b0b98f2 ---- /dev/null -+++ b/vendor/github.com/moby/spdystream/spdy/options_test.go -@@ -0,0 +1,33 @@ -+package spdy -+ -+import ( -+ "net" -+ "testing" -+) -+ -+func TestNewFramerWithOptions(t *testing.T) { -+ serverConn, clientConn := net.Pipe() -+ defer func() { -+ _ = clientConn.Close() -+ _ = serverConn.Close() -+ }() -+ -+ framer, err := NewFramerWithOptions(clientConn, clientConn, -+ WithMaxControlFramePayloadSize(1024), -+ WithMaxHeaderFieldSize(128), -+ WithMaxHeaderCount(16), -+ ) -+ if err != nil { -+ t.Fatalf("Error creating spdy connection with options: %s", err) -+ } -+ -+ if got := framer.maxFrameLength; got != 1024 { -+ t.Fatalf("Unexpected MaxControlFramePayloadSize: %d", got) -+ } -+ if got := framer.maxHeaderFieldSize; got != 128 { -+ t.Fatalf("Unexpected MaxHeaderFieldSize: %d", got) -+ } -+ if got := framer.maxHeaderCount; got != 16 { -+ t.Fatalf("Unexpected MaxHeaderCount: %d", got) -+ } -+} -diff --git a/vendor/github.com/moby/spdystream/spdy/read.go b/vendor/github.com/moby/spdystream/spdy/read.go -index 75ea045..2abb694 100644 ---- a/vendor/github.com/moby/spdystream/spdy/read.go -+++ b/vendor/github.com/moby/spdystream/spdy/read.go -@@ -1,19 +1,3 @@ --/* -- Copyright 2014-2021 Docker Inc. -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. --*/ -- - // Copyright 2011 The Go Authors. All rights reserved. - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -@@ -24,6 +8,7 @@ import ( - "compress/zlib" - "encoding/binary" - "io" -+ "io/ioutil" - "net/http" - "strings" - ) -@@ -59,6 +44,11 @@ func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) error { - if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil { - return err - } -+ // Each setting is 8 bytes (4-byte id + 4-byte value). -+ // Payload is 4 bytes for numSettings + numSettings*8. -+ if h.length < 4 || numSettings > (h.length-4)/8 { -+ return &Error{InvalidControlFrame, 0} -+ } - frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings) - for i := uint32(0); i < numSettings; i++ { - if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil { -@@ -177,8 +167,19 @@ func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) ( - if err := binary.Read(f.r, binary.BigEndian, &length); err != nil { - return nil, err - } -+ maxControlFramePayload := uint32(MaxDataLength) -+ if f.maxFrameLength > 0 { -+ maxControlFramePayload = f.maxFrameLength -+ } -+ - flags := ControlFlags((length & 0xff000000) >> 24) - length &= 0xffffff -+ if length > maxControlFramePayload { -+ if _, err := io.CopyN(ioutil.Discard, f.r, int64(length)); err != nil { -+ return nil, err -+ } -+ return nil, &Error{InvalidControlFrame, 0} -+ } - header := ControlFrameHeader{version, frameType, flags, length} - cframe, err := newControlFrame(frameType) - if err != nil { -@@ -190,11 +191,22 @@ func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) ( - return cframe, nil - } - --func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) { -+func (f *Framer) parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) { - var numHeaders uint32 - if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil { - return nil, err - } -+ maxHeaders := defaultMaxHeaderCount -+ if f.maxHeaderCount > 0 { -+ maxHeaders = f.maxHeaderCount -+ } -+ if numHeaders > maxHeaders { -+ return nil, &Error{InvalidControlFrame, streamId} -+ } -+ maxFieldSize := defaultMaxHeaderFieldSize -+ if f.maxHeaderFieldSize > 0 { -+ maxFieldSize = f.maxHeaderFieldSize -+ } - var e error - h := make(http.Header, int(numHeaders)) - for i := 0; i < int(numHeaders); i++ { -@@ -202,6 +214,9 @@ func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) - if err := binary.Read(r, binary.BigEndian, &length); err != nil { - return nil, err - } -+ if length > maxFieldSize { -+ return nil, &Error{InvalidControlFrame, streamId} -+ } - nameBytes := make([]byte, length) - if _, err := io.ReadFull(r, nameBytes); err != nil { - return nil, err -@@ -217,6 +232,9 @@ func parseHeaderValueBlock(r io.Reader, streamId StreamId) (http.Header, error) - if err := binary.Read(r, binary.BigEndian, &length); err != nil { - return nil, err - } -+ if length > maxFieldSize { -+ return nil, &Error{InvalidControlFrame, streamId} -+ } - value := make([]byte, length) - if _, err := io.ReadFull(r, value); err != nil { - return nil, err -@@ -256,7 +274,7 @@ func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) - } - reader = f.headerDecompressor - } -- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId) -+ frame.Headers, err = f.parseHeaderValueBlock(reader, frame.StreamId) - if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) { - err = &Error{WrongCompressedPayloadSize, 0} - } -@@ -288,7 +306,7 @@ func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) e - } - reader = f.headerDecompressor - } -- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId) -+ frame.Headers, err = f.parseHeaderValueBlock(reader, frame.StreamId) - if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) { - err = &Error{WrongCompressedPayloadSize, 0} - } -@@ -320,7 +338,7 @@ func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) err - } - reader = f.headerDecompressor - } -- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId) -+ frame.Headers, err = f.parseHeaderValueBlock(reader, frame.StreamId) - if !f.headerCompressionDisabled && (err == io.EOF && f.headerReader.N == 0 || f.headerReader.N != 0) { - err = &Error{WrongCompressedPayloadSize, 0} - } -diff --git a/vendor/github.com/moby/spdystream/spdy/types.go b/vendor/github.com/moby/spdystream/spdy/types.go -index a254a43..a552861 100644 ---- a/vendor/github.com/moby/spdystream/spdy/types.go -+++ b/vendor/github.com/moby/spdystream/spdy/types.go -@@ -1,23 +1,9 @@ --/* -- Copyright 2014-2021 Docker Inc. -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. --*/ -- - // Copyright 2011 The Go Authors. All rights reserved. - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - -+// Modifications Copyright 2014-2021 Docker Inc. -+ - // Package spdy implements the SPDY protocol (currently SPDY/3), described in - // http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3. - package spdy -@@ -63,8 +49,20 @@ const ( - ) - - // MaxDataLength is the maximum number of bytes that can be stored in one frame. -+// -+// SPDY frame headers encode the payload length using a 24-bit field, -+// so the maximum representable size for both data and control frames -+// is 2^24-1 bytes. -+// -+// See the SPDY/3 specification, "Frame Format": -+// https://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1/ - const MaxDataLength = 1<<24 - 1 - -+const ( -+ defaultMaxHeaderFieldSize uint32 = 1 << 20 -+ defaultMaxHeaderCount uint32 = 1000 -+) -+ - // headerValueSepator separates multiple header values. - const headerValueSeparator = "\x00" - -@@ -269,6 +267,10 @@ type Framer struct { - r io.Reader - headerReader io.LimitedReader - headerDecompressor io.ReadCloser -+ -+ maxFrameLength uint32 // overrides the default frame payload length limit. -+ maxHeaderFieldSize uint32 // overrides the default per-header name/value length limit. -+ maxHeaderCount uint32 // overrides the default header count limit. - } - - // NewFramer allocates a new Framer for a given SPDY connection, represented by -@@ -276,6 +278,16 @@ type Framer struct { - // from/to the Reader and Writer, so the caller should pass in an appropriately - // buffered implementation to optimize performance. - func NewFramer(w io.Writer, r io.Reader) (*Framer, error) { -+ return newFramer(w, r) -+} -+ -+// NewFramerWithOptions allocates a new Framer for a given SPDY connection and -+// applies frame parsing limits via options. -+func NewFramerWithOptions(w io.Writer, r io.Reader, opts ...FramerOption) (*Framer, error) { -+ return newFramer(w, r, opts...) -+} -+ -+func newFramer(w io.Writer, r io.Reader, opts ...FramerOption) (*Framer, error) { - compressBuf := new(bytes.Buffer) - compressor, err := zlib.NewWriterLevelDict(compressBuf, zlib.BestCompression, []byte(headerDictionary)) - if err != nil { -@@ -287,5 +299,10 @@ func NewFramer(w io.Writer, r io.Reader) (*Framer, error) { - headerCompressor: compressor, - r: r, - } -+ for _, opt := range opts { -+ if opt != nil { -+ opt(framer) -+ } -+ } - return framer, nil - } -diff --git a/vendor/github.com/moby/spdystream/spdy/write.go b/vendor/github.com/moby/spdystream/spdy/write.go -index ab6d91f..75084d3 100644 ---- a/vendor/github.com/moby/spdystream/spdy/write.go -+++ b/vendor/github.com/moby/spdystream/spdy/write.go -@@ -1,19 +1,3 @@ --/* -- Copyright 2014-2021 Docker Inc. -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. --*/ -- - // Copyright 2011 The Go Authors. All rights reserved. - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -@@ -23,6 +7,7 @@ package spdy - import ( - "encoding/binary" - "io" -+ "math" - "net/http" - "strings" - ) -@@ -63,13 +48,21 @@ func (frame *RstStreamFrame) write(f *Framer) (err error) { - func (frame *SettingsFrame) write(f *Framer) (err error) { - frame.CFHeader.version = Version - frame.CFHeader.frameType = TypeSettings -- frame.CFHeader.length = uint32(len(frame.FlagIdValues)*8 + 4) -+ payloadLen := len(frame.FlagIdValues)*8 + 4 -+ if payloadLen > MaxDataLength { -+ return &Error{InvalidControlFrame, 0} -+ } -+ frame.CFHeader.length = uint32(payloadLen) - - // Serialize frame to Writer. - if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { - return - } -- if err = binary.Write(f.w, binary.BigEndian, uint32(len(frame.FlagIdValues))); err != nil { -+ n := len(frame.FlagIdValues) -+ if uint64(n) > math.MaxUint32 { -+ return &Error{InvalidControlFrame, 0} -+ } -+ if err = binary.Write(f.w, binary.BigEndian, uint32(n)); err != nil { - return - } - for _, flagIdValue := range frame.FlagIdValues { -@@ -170,29 +163,41 @@ func writeControlFrameHeader(w io.Writer, h ControlFrameHeader) error { - - func writeHeaderValueBlock(w io.Writer, h http.Header) (n int, err error) { - n = 0 -- if err = binary.Write(w, binary.BigEndian, uint32(len(h))); err != nil { -+ numHeaders := len(h) -+ if numHeaders > math.MaxInt32 { -+ return n, &Error{InvalidControlFrame, 0} -+ } -+ if err = binary.Write(w, binary.BigEndian, uint32(numHeaders)); err != nil { - return - } -- n += 2 -+ n += 4 - for name, values := range h { -- if err = binary.Write(w, binary.BigEndian, uint32(len(name))); err != nil { -+ nameLen := len(name) -+ if nameLen > math.MaxInt32 { -+ return n, &Error{InvalidControlFrame, 0} -+ } -+ if err = binary.Write(w, binary.BigEndian, uint32(nameLen)); err != nil { - return - } -- n += 2 -+ n += 4 - name = strings.ToLower(name) - if _, err = io.WriteString(w, name); err != nil { - return - } -- n += len(name) -+ n += nameLen - v := strings.Join(values, headerValueSeparator) -- if err = binary.Write(w, binary.BigEndian, uint32(len(v))); err != nil { -+ vLen := len(v) -+ if vLen > math.MaxInt32 { -+ return n, &Error{InvalidControlFrame, 0} -+ } -+ if err = binary.Write(w, binary.BigEndian, uint32(vLen)); err != nil { - return - } -- n += 2 -+ n += 4 - if _, err = io.WriteString(w, v); err != nil { - return - } -- n += len(v) -+ n += vLen - } - return - } -@@ -216,7 +221,11 @@ func (f *Framer) writeSynStreamFrame(frame *SynStreamFrame) (err error) { - // Set ControlFrameHeader. - frame.CFHeader.version = Version - frame.CFHeader.frameType = TypeSynStream -- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 10) -+ hLen := len(f.headerBuf.Bytes()) + 10 -+ if hLen > MaxDataLength { -+ return &Error{InvalidControlFrame, 0} -+ } -+ frame.CFHeader.length = uint32(hLen) - - // Serialize frame to Writer. - if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { -@@ -260,7 +269,11 @@ func (f *Framer) writeSynReplyFrame(frame *SynReplyFrame) (err error) { - // Set ControlFrameHeader. - frame.CFHeader.version = Version - frame.CFHeader.frameType = TypeSynReply -- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4) -+ hLen := len(f.headerBuf.Bytes()) + 4 -+ if hLen > MaxDataLength { -+ return &Error{InvalidControlFrame, 0} -+ } -+ frame.CFHeader.length = uint32(hLen) - - // Serialize frame to Writer. - if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { -@@ -295,7 +308,11 @@ func (f *Framer) writeHeadersFrame(frame *HeadersFrame) (err error) { - // Set ControlFrameHeader. - frame.CFHeader.version = Version - frame.CFHeader.frameType = TypeHeaders -- frame.CFHeader.length = uint32(len(f.headerBuf.Bytes()) + 4) -+ hLen := len(f.headerBuf.Bytes()) + 4 -+ if hLen > MaxDataLength { -+ return &Error{InvalidControlFrame, 0} -+ } -+ frame.CFHeader.length = uint32(hLen) - - // Serialize frame to Writer. - if err = writeControlFrameHeader(f.w, frame.CFHeader); err != nil { -@@ -323,7 +340,11 @@ func (f *Framer) writeDataFrame(frame *DataFrame) (err error) { - if err = binary.Write(f.w, binary.BigEndian, frame.StreamId); err != nil { - return - } -- flagsAndLength := uint32(frame.Flags)<<24 | uint32(len(frame.Data)) -+ dLen := len(frame.Data) -+ if dLen > MaxDataLength { -+ return &Error{InvalidDataFrame, frame.StreamId} -+ } -+ flagsAndLength := uint32(frame.Flags)<<24 | uint32(dLen) - if err = binary.Write(f.w, binary.BigEndian, flagsAndLength); err != nil { - return - } --- -2.45.4 - diff --git a/SPECS/containerd2/containerd2.signatures.json b/SPECS/containerd2/containerd2.signatures.json index d49f7f913eb..a05c234b20f 100644 --- a/SPECS/containerd2/containerd2.signatures.json +++ b/SPECS/containerd2/containerd2.signatures.json @@ -2,6 +2,6 @@ "Signatures": { "containerd.service": "a07bfcf412669b06673190b0779f48e652c9adcf1758289e849a00802804eec8", "containerd.toml": "5b3821236f09b4c858e0e098bbe1400f4dbbb47d360e39d21c61858b088c2896", - "containerd-2.0.0.tar.gz": "346d644e1b96e1f4a39bfe9d1eb0eb01ca676f806c12d95e5dbe35325bbc1780" + "containerd-2.1.6.tar.gz": "9b13537e5d61b9cf301295a807751447cc7c86fd79bb37ac5630455013d353a5" } -} \ No newline at end of file +} diff --git a/SPECS/containerd2/containerd2.spec b/SPECS/containerd2/containerd2.spec index aa11f6f9a37..a645457fb43 100644 --- a/SPECS/containerd2/containerd2.spec +++ b/SPECS/containerd2/containerd2.spec @@ -1,11 +1,11 @@ %global debug_package %{nil} %define upstream_name containerd -%define commit_hash 207ad711eabd375a01713109a8a197d197ff6542 +%define commit_hash c74fd8780002eb26bd5940ae339d690d891221c2 Summary: Industry-standard container runtime Name: %{upstream_name}2 -Version: 2.0.0 -Release: 19%{?dist} +Version: 2.1.6 +Release: 1%{?dist} License: ASL 2.0 Group: Tools/Container URL: https://www.containerd.io @@ -16,19 +16,9 @@ Source0: https://github.com/containerd/containerd/archive/v%{version}.tar.gz#/%{ Source1: containerd.service Source2: containerd.toml -Patch0: CVE-2024-45338.patch -Patch1: CVE-2025-27144.patch -Patch2: CVE-2024-40635.patch -Patch3: CVE-2025-22872.patch -Patch4: CVE-2025-47291.patch -Patch5: multi-snapshotters-support.patch -Patch6: tardev-support.patch -Patch7: CVE-2024-25621.patch -Patch8: CVE-2025-64329.patch -Patch9: fix-credential-leak-in-cri-errors.patch -Patch10:CVE-2025-47911.patch -Patch11:CVE-2025-58190.patch -Patch12:CVE-2026-35469.patch +Patch0: multi-snapshotters-support.patch +Patch1: tardev-support.patch +Patch2: fix-credential-leak-in-cri-errors.patch %{?systemd_requires} @@ -105,6 +95,14 @@ fi %dir /opt/containerd/lib %changelog +* Fri Apr 17 2026 Jyoti Kanase - 2.1.6-1 +- Upgrade to 2.1.6 +- Remove CVE patches fixed in upstream: CVE-2024-25621, CVE-2024-40635, + CVE-2024-45338, CVE-2025-22872, CVE-2025-27144, CVE-2025-47291, + CVE-2025-47911, CVE-2025-58190, CVE-2025-64329 +- Modify fix-credential-leak-in-cri-errors patch to keep only 2/2 not yet merged in upstream +- Rebase multi-snapshotters-support patch for 2.1.6 + * Tue Apr 07 2026 Kanishk Bansal - 2.0.0-19 - Patch CVE-2026-35469 diff --git a/SPECS/containerd2/fix-credential-leak-in-cri-errors.patch b/SPECS/containerd2/fix-credential-leak-in-cri-errors.patch index 909c179c259..c6ad3e29486 100644 --- a/SPECS/containerd2/fix-credential-leak-in-cri-errors.patch +++ b/SPECS/containerd2/fix-credential-leak-in-cri-errors.patch @@ -1,294 +1,3 @@ -From a34e45d0fa2a7ddefff1a0871c9bf9e3c62bda17 Mon Sep 17 00:00:00 2001 -From: Andrey Noskov -Date: Thu, 6 Nov 2025 13:34:38 +0100 -Subject: [PATCH 1/2] fix: redact all query parameters in CRI error logs - -Signed-off-by: Andrey Noskov ---- - .../cri/instrument/instrumented_service.go | 8 ++ - internal/cri/util/sanitize.go | 93 +++++++++++++ - internal/cri/util/sanitize_test.go | 128 ++++++++++++++++++ - 3 files changed, 229 insertions(+) - create mode 100644 internal/cri/util/sanitize.go - create mode 100644 internal/cri/util/sanitize_test.go - -diff --git a/internal/cri/instrument/instrumented_service.go b/internal/cri/instrument/instrumented_service.go -index c2f5c8de99..f06315a6bd 100644 ---- a/internal/cri/instrument/instrumented_service.go -+++ b/internal/cri/instrument/instrumented_service.go -@@ -351,6 +351,8 @@ func (in *instrumentedService) PullImage(ctx context.Context, r *runtime.PullIma - log.G(ctx).Infof("PullImage %q", r.GetImage().GetImage()) - defer func() { - if err != nil { -+ // Sanitize error to remove sensitive information -+ err = ctrdutil.SanitizeError(err) - log.G(ctx).WithError(err).Errorf("PullImage %q failed", r.GetImage().GetImage()) - } else { - log.G(ctx).Infof("PullImage %q returns image reference %q", -@@ -369,6 +371,8 @@ func (in *instrumentedService) ListImages(ctx context.Context, r *runtime.ListIm - log.G(ctx).Tracef("ListImages with filter %+v", r.GetFilter()) - defer func() { - if err != nil { -+ // Sanitize error to remove sensitive information -+ err = ctrdutil.SanitizeError(err) - log.G(ctx).WithError(err).Errorf("ListImages with filter %+v failed", r.GetFilter()) - } else { - log.G(ctx).Tracef("ListImages with filter %+v returns image list %+v", -@@ -386,6 +390,8 @@ func (in *instrumentedService) ImageStatus(ctx context.Context, r *runtime.Image - log.G(ctx).Tracef("ImageStatus for %q", r.GetImage().GetImage()) - defer func() { - if err != nil { -+ // Sanitize error to remove sensitive information -+ err = ctrdutil.SanitizeError(err) - log.G(ctx).WithError(err).Errorf("ImageStatus for %q failed", r.GetImage().GetImage()) - } else { - log.G(ctx).Tracef("ImageStatus for %q returns image status %+v", -@@ -404,6 +410,8 @@ func (in *instrumentedService) RemoveImage(ctx context.Context, r *runtime.Remov - log.G(ctx).Infof("RemoveImage %q", r.GetImage().GetImage()) - defer func() { - if err != nil { -+ // Sanitize error to remove sensitive information -+ err = ctrdutil.SanitizeError(err) - log.G(ctx).WithError(err).Errorf("RemoveImage %q failed", r.GetImage().GetImage()) - } else { - log.G(ctx).Infof("RemoveImage %q returns successfully", r.GetImage().GetImage()) -diff --git a/internal/cri/util/sanitize.go b/internal/cri/util/sanitize.go -new file mode 100644 -index 0000000000..d50a15ebf6 ---- /dev/null -+++ b/internal/cri/util/sanitize.go -@@ -0,0 +1,93 @@ -+/* -+ Copyright The containerd Authors. -+ -+ Licensed under the Apache License, Version 2.0 (the "License"); -+ you may not use this file except in compliance with the License. -+ You may obtain a copy of the License at -+ -+ http://www.apache.org/licenses/LICENSE-2.0 -+ -+ Unless required by applicable law or agreed to in writing, software -+ distributed under the License is distributed on an "AS IS" BASIS, -+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ See the License for the specific language governing permissions and -+ limitations under the License. -+*/ -+ -+package util -+ -+import ( -+ "errors" -+ "net/url" -+ "strings" -+) -+ -+// SanitizeError sanitizes an error by redacting sensitive information in URLs. -+// If the error contains a *url.Error, it parses and sanitizes the URL. -+// Otherwise, it returns the error unchanged. -+func SanitizeError(err error) error { -+ if err == nil { -+ return nil -+ } -+ -+ // Check if the error is or contains a *url.Error -+ var urlErr *url.Error -+ if errors.As(err, &urlErr) { -+ // Parse and sanitize the URL -+ sanitizedURL := sanitizeURL(urlErr.URL) -+ if sanitizedURL != urlErr.URL { -+ // Wrap with sanitized url.Error -+ return &sanitizedError{ -+ original: err, -+ sanitizedURL: sanitizedURL, -+ urlError: urlErr, -+ } -+ } -+ return err -+ } -+ -+ // No sanitization needed for non-URL errors -+ return err -+} -+ -+// sanitizeURL properly parses a URL and redacts all query parameters. -+func sanitizeURL(rawURL string) string { -+ parsed, err := url.Parse(rawURL) -+ if err != nil { -+ // If URL parsing fails, return original (malformed URLs shouldn't leak tokens) -+ return rawURL -+ } -+ -+ // Check if URL has query parameters -+ query := parsed.Query() -+ if len(query) == 0 { -+ return rawURL -+ } -+ -+ // Redact all query parameters -+ for param := range query { -+ query.Set(param, "[REDACTED]") -+ } -+ -+ // Reconstruct URL with sanitized query -+ parsed.RawQuery = query.Encode() -+ return parsed.String() -+} -+ -+// sanitizedError wraps an error containing a *url.Error with a sanitized URL. -+type sanitizedError struct { -+ original error -+ sanitizedURL string -+ urlError *url.Error -+} -+ -+// Error returns the error message with the sanitized URL. -+func (e *sanitizedError) Error() string { -+ // Replace all occurrences of the original URL with the sanitized version -+ return strings.ReplaceAll(e.original.Error(), e.urlError.URL, e.sanitizedURL) -+} -+ -+// Unwrap returns the original error for error chain traversal. -+func (e *sanitizedError) Unwrap() error { -+ return e.original -+} -diff --git a/internal/cri/util/sanitize_test.go b/internal/cri/util/sanitize_test.go -new file mode 100644 -index 0000000000..03e4fb2694 ---- /dev/null -+++ b/internal/cri/util/sanitize_test.go -@@ -0,0 +1,128 @@ -+/* -+ Copyright The containerd Authors. -+ -+ Licensed under the Apache License, Version 2.0 (the "License"); -+ you may not use this file except in compliance with the License. -+ You may obtain a copy of the License at -+ -+ http://www.apache.org/licenses/LICENSE-2.0 -+ -+ Unless required by applicable law or agreed to in writing, software -+ distributed under the License is distributed on an "AS IS" BASIS, -+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+ See the License for the specific language governing permissions and -+ limitations under the License. -+*/ -+ -+package util -+ -+import ( -+ "errors" -+ "fmt" -+ "net/url" -+ "testing" -+ -+ "github.com/stretchr/testify/assert" -+ "github.com/stretchr/testify/require" -+) -+ -+func TestSanitizeError_SimpleURLError(t *testing.T) { -+ // Create a url.Error with sensitive info -+ originalURL := "https://storage.blob.core.windows.net/container/blob?sig=SECRET&sv=2020" -+ urlErr := &url.Error{ -+ Op: "Get", -+ URL: originalURL, -+ Err: fmt.Errorf("connection timeout"), -+ } -+ -+ // Sanitize -+ sanitized := SanitizeError(urlErr) -+ require.NotNil(t, sanitized) -+ -+ // Check it's a sanitizedError with correct properties -+ sanitizedErr, ok := sanitized.(*sanitizedError) -+ require.True(t, ok, "Should return *sanitizedError type") -+ assert.Equal(t, urlErr, sanitizedErr.original) -+ assert.Equal(t, urlErr, sanitizedErr.urlError) -+ assert.Equal(t, "https://storage.blob.core.windows.net/container/blob?sig=%5BREDACTED%5D&sv=%5BREDACTED%5D", sanitizedErr.sanitizedURL) -+ -+ // Test Error() method - verifies ReplaceAll functionality -+ expected := "Get \"https://storage.blob.core.windows.net/container/blob?sig=%5BREDACTED%5D&sv=%5BREDACTED%5D\": connection timeout" -+ assert.Equal(t, expected, sanitized.Error()) -+} -+ -+func TestSanitizeError_WrappedError(t *testing.T) { -+ originalURL := "https://storage.blob.core.windows.net/blob?sig=SECRET&sv=2020" -+ urlErr := &url.Error{ -+ Op: "Get", -+ URL: originalURL, -+ Err: fmt.Errorf("timeout"), -+ } -+ -+ wrappedErr := fmt.Errorf("image pull failed: %w", urlErr) -+ -+ // Sanitize -+ sanitized := SanitizeError(wrappedErr) -+ -+ // Test Error() method with wrapped error - verifies ReplaceAll works in wrapped context -+ sanitizedMsg := sanitized.Error() -+ assert.NotContains(t, sanitizedMsg, "SECRET", "Secret should be sanitized") -+ assert.Contains(t, sanitizedMsg, "image pull failed", "Wrapper message should be preserved") -+ assert.Contains(t, sanitizedMsg, "%5BREDACTED%5D", "Should contain sanitized marker") -+ -+ // Should still be able to unwrap to url.Error -+ var targetURLErr *url.Error -+ assert.True(t, errors.As(sanitized, &targetURLErr), -+ "Should be able to find *url.Error in sanitized error chain") -+ -+ // Verify url.Error properties are preserved -+ assert.Equal(t, "Get", targetURLErr.Op) -+ assert.Contains(t, targetURLErr.Err.Error(), "timeout") -+} -+ -+func TestSanitizeError_NonURLError(t *testing.T) { -+ // Regular error without url.Error -+ regularErr := fmt.Errorf("some error occurred") -+ -+ sanitized := SanitizeError(regularErr) -+ -+ // Should return the exact same error object -+ assert.Equal(t, regularErr, sanitized, -+ "Non-URL errors should pass through unchanged") -+} -+ -+func TestSanitizeError_NilError(t *testing.T) { -+ sanitized := SanitizeError(nil) -+ assert.Nil(t, sanitized, "nil error should return nil") -+} -+ -+func TestSanitizeError_NoQueryParams(t *testing.T) { -+ // URL without any query parameters -+ urlErr := &url.Error{ -+ Op: "Get", -+ URL: "https://registry.example.com/v2/image/manifests/latest", -+ Err: fmt.Errorf("not found"), -+ } -+ -+ sanitized := SanitizeError(urlErr) -+ -+ // Should return the same error object (no sanitization needed) -+ assert.Equal(t, urlErr, sanitized, -+ "Errors without query params should pass through unchanged") -+} -+ -+func TestSanitizedError_Unwrap(t *testing.T) { -+ originalURL := "https://storage.blob.core.windows.net/blob?sig=SECRET" -+ urlErr := &url.Error{ -+ Op: "Get", -+ URL: originalURL, -+ Err: fmt.Errorf("timeout"), -+ } -+ -+ sanitized := SanitizeError(urlErr) -+ -+ // Should be able to unwrap -+ unwrapped := errors.Unwrap(sanitized) -+ assert.NotNil(t, unwrapped, "Should be able to unwrap sanitized error") -+ assert.Equal(t, urlErr, unwrapped, "Unwrapped should be the original error") -+} --- -2.45.4 - - From 50e383e3907d04aeaec85853edfaa9ab34be1006 Mon Sep 17 00:00:00 2001 From: Aadhar Agarwal Date: Tue, 20 Jan 2026 22:16:30 +0000 @@ -398,4 +107,3 @@ index f06315a6bd..4379f95997 100644 -- 2.45.4 - diff --git a/SPECS/containerd2/multi-snapshotters-support.patch b/SPECS/containerd2/multi-snapshotters-support.patch index 3fae23406fb..5e9073121b0 100644 --- a/SPECS/containerd2/multi-snapshotters-support.patch +++ b/SPECS/containerd2/multi-snapshotters-support.patch @@ -5,19 +5,19 @@ Subject: [PATCH] Add multi-snapshotter support --- internal/cri/server/container_status_test.go | 2 +- - internal/cri/server/images/image_pull.go | 37 +++++++++++-------- + internal/cri/server/images/image_pull.go | 38 +++++++++++-------- internal/cri/server/images/image_pull_test.go | 2 +- internal/cri/server/podsandbox/controller.go | 2 +- internal/cri/server/podsandbox/sandbox_run.go | 30 ++++++++------- internal/cri/server/service.go | 2 +- - internal/cri/store/image/image.go | 29 ++++++++++++--- - 7 files changed, 66 insertions(+), 38 deletions(-) + internal/cri/store/image/image.go | 29 +++++++++++--- + 7 files changed, 66 insertions(+), 39 deletions(-) diff --git a/internal/cri/server/container_status_test.go b/internal/cri/server/container_status_test.go -index 05b1650..71dcc10 100644 +index f53fb1a..0063ac0 100644 --- a/internal/cri/server/container_status_test.go +++ b/internal/cri/server/container_status_test.go -@@ -302,7 +302,7 @@ func (s *fakeImageService) LocalResolve(refOrID string) (imagestore.Image, error +@@ -300,7 +300,7 @@ func (s *fakeImageService) LocalResolve(refOrID string) (imagestore.Image, error func (s *fakeImageService) ImageFSPaths() map[string]string { return make(map[string]string) } @@ -27,10 +27,10 @@ index 05b1650..71dcc10 100644 } diff --git a/internal/cri/server/images/image_pull.go b/internal/cri/server/images/image_pull.go -index e59b88b..f9c90b7 100644 +index 113de6e..680c205 100644 --- a/internal/cri/server/images/image_pull.go +++ b/internal/cri/server/images/image_pull.go -@@ -96,6 +96,15 @@ import ( +@@ -99,6 +99,15 @@ import ( // PullImage pulls an image with authentication config. func (c *GRPCCRIImageService) PullImage(ctx context.Context, r *runtime.PullImageRequest) (_ *runtime.PullImageResponse, err error) { @@ -46,7 +46,7 @@ index e59b88b..f9c90b7 100644 imageRef := r.GetImage().GetImage() -@@ -110,14 +119,14 @@ func (c *GRPCCRIImageService) PullImage(ctx context.Context, r *runtime.PullImag +@@ -113,14 +122,14 @@ func (c *GRPCCRIImageService) PullImage(ctx context.Context, r *runtime.PullImag return ParseAuth(hostauth, host) } @@ -63,18 +63,19 @@ index e59b88b..f9c90b7 100644 span := tracing.SpanFromContext(ctx) defer func() { // TODO: add domain label for imagePulls metrics, and we may need to provide a mechanism -@@ -167,10 +176,6 @@ func (c *CRIImageService) PullImage(ctx context.Context, name string, credential - ) +@@ -165,11 +174,6 @@ func (c *CRIImageService) PullImage(ctx context.Context, name string, credential + return "", fmt.Errorf("failed to parse image_pull_progress_timeout %q: %w", c.config.ImagePullProgressTimeout, err) + } - defer pcancel() - snapshotter, err := c.snapshotterFromPodSandboxConfig(ctx, ref, sandboxConfig) - if err != nil { - return "", err - } - log.G(ctx).Debugf("PullImage %q with snapshotter %s", ref, snapshotter) +- span.SetAttributes( tracing.Attribute("image.ref", ref), -@@ -761,17 +766,19 @@ func (rt *pullRequestReporterRoundTripper) RoundTrip(req *http.Request) (*http.R + tracing.Attribute("snapshotter.name", snapshotter), +@@ -828,17 +832,19 @@ func (rt *pullRequestReporterRoundTripper) RoundTrip(req *http.Request) (*http.R // Once we know the runtime, try to override default snapshotter if it is set for this runtime. // See https://github.com/containerd/containerd/issues/6657 func (c *CRIImageService) snapshotterFromPodSandboxConfig(ctx context.Context, imageRef string, @@ -104,10 +105,10 @@ index e59b88b..f9c90b7 100644 // TODO: Ensure error is returned if runtime not found? diff --git a/internal/cri/server/images/image_pull_test.go b/internal/cri/server/images/image_pull_test.go -index bc79e35..af6a451 100644 +index cc10721..4d8ac0f 100644 --- a/internal/cri/server/images/image_pull_test.go +++ b/internal/cri/server/images/image_pull_test.go -@@ -429,7 +429,7 @@ func TestSnapshotterFromPodSandboxConfig(t *testing.T) { +@@ -428,7 +428,7 @@ func TestSnapshotterFromPodSandboxConfig(t *testing.T) { Platform: platforms.DefaultSpec(), Snapshotter: runtimeSnapshotter, } @@ -117,10 +118,10 @@ index bc79e35..af6a451 100644 if tt.expectedErr { assert.Error(t, err) diff --git a/internal/cri/server/podsandbox/controller.go b/internal/cri/server/podsandbox/controller.go -index a185a4c..8fd032b 100644 +index fd9c5db..5af4c85 100644 --- a/internal/cri/server/podsandbox/controller.go +++ b/internal/cri/server/podsandbox/controller.go -@@ -110,7 +110,7 @@ type RuntimeService interface { +@@ -112,7 +112,7 @@ type RuntimeService interface { type ImageService interface { LocalResolve(refOrID string) (imagestore.Image, error) GetImage(id string) (imagestore.Image, error) @@ -130,10 +131,10 @@ index a185a4c..8fd032b 100644 PinnedImage(string) string } diff --git a/internal/cri/server/podsandbox/sandbox_run.go b/internal/cri/server/podsandbox/sandbox_run.go -index 53d949f..35e0075 100644 +index d850a3a..0d261f9 100644 --- a/internal/cri/server/podsandbox/sandbox_run.go +++ b/internal/cri/server/podsandbox/sandbox_run.go -@@ -77,23 +77,25 @@ func (c *Controller) Start(ctx context.Context, id string) (cin sandbox.Controll +@@ -78,23 +78,25 @@ func (c *Controller) Start(ctx context.Context, id string) (cin sandbox.Controll sandboxImage := c.getSandboxImageName() // Ensure sandbox container image snapshot. @@ -168,7 +169,7 @@ index 53d949f..35e0075 100644 // Create sandbox container root directories. sandboxRootDir := c.getSandboxRootDir(id) -@@ -173,7 +175,7 @@ func (c *Controller) Start(ctx context.Context, id string) (cin sandbox.Controll +@@ -187,7 +189,7 @@ func (c *Controller) Start(ctx context.Context, id string) (cin sandbox.Controll snapshotterOpt = append(snapshotterOpt, extraSOpts...) opts := []containerd.NewContainerOpts{ @@ -177,7 +178,7 @@ index 53d949f..35e0075 100644 customopts.WithNewSnapshot(id, containerdImage, snapshotterOpt...), containerd.WithSpec(spec, specOpts...), containerd.WithContainerLabels(sandboxLabels), -@@ -299,17 +301,19 @@ func (c *Controller) Create(_ctx context.Context, info sandbox.Sandbox, opts ... +@@ -313,17 +315,19 @@ func (c *Controller) Create(_ctx context.Context, info sandbox.Sandbox, opts ... return c.store.Save(podSandbox) } @@ -201,7 +202,7 @@ index 53d949f..35e0075 100644 return nil, fmt.Errorf("failed to pull image %q: %w", ref, err) } diff --git a/internal/cri/server/service.go b/internal/cri/server/service.go -index 37d66f0..5d1546e 100644 +index 8b65b14..2ccf355 100644 --- a/internal/cri/server/service.go +++ b/internal/cri/server/service.go @@ -97,7 +97,7 @@ type RuntimeService interface { @@ -214,7 +215,7 @@ index 37d66f0..5d1546e 100644 CheckImages(ctx context.Context) error diff --git a/internal/cri/store/image/image.go b/internal/cri/store/image/image.go -index 5887e75..43ecf0d 100644 +index fc0ade2..a42108d 100644 --- a/internal/cri/store/image/image.go +++ b/internal/cri/store/image/image.go @@ -20,6 +20,7 @@ import ( @@ -275,5 +276,4 @@ index 5887e75..43ecf0d 100644 } -- -2.34.1 - +2.45.4 diff --git a/cgmanifest.json b/cgmanifest.json index 4d52a681761..b2d5fd9cd9a 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -2067,8 +2067,8 @@ "type": "other", "other": { "name": "containerd2", - "version": "2.0.0", - "downloadUrl": "https://github.com/containerd/containerd/archive/v2.0.0.tar.gz" + "version": "2.1.6", + "downloadUrl": "https://github.com/containerd/containerd/archive/v2.1.6.tar.gz" } } },