Package: release.debian.org
Severity: normal
Tags: bookworm
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:containerd
User: [email protected]
Usertags: pu
[ Reason ]
Backport patch for CVE-2025-64329.
The previous upload 1.6.20~ds1-1+deb12u2 had a mistake in the changelog,
and while it fixed CVE-2024-40635, it claimed to have fixed
CVE-2025-64329.
This has been discussed with Maintainer and Security Team, the security
tracker had been updated [1], and Security Team confirmed that I should
proceed with an upload to bookworm-updates.
There's a bit of churn in this debdiff: on top of fixing CVE-2025-64329,
the changes also include:
- fix the _previous_ changelog entry
- rename a patch that fixes a CVE, for clarity
You can also see the changes on Salsa at [2], in case you find it easier
to see the Git history.
[1]: https://deb.freexian.com/extended-lts/tracker/source-package/containerd
[2]:
https://salsa.debian.org/arnaudr/containerd/-/commits/debian/bookworm?ref_type=heads
[ Impact ]
Impact of CVE-2025-64329 is that a malicious user can exhaust memory on
the host by exploiting a bug in the CRI Attach implementation (goroutine
leaks).
[ Tests ]
I didn't come up with a test to confirm the fix , but the patch (that
comes from upstream) applies rather cleany. I did test that there's no
regression (ie. attaching to a running container still works).
[ Risks ]
The patch is rather trivial.
[ Checklist ]
[x] *all* changes are documented in the d/changelog
[x] I reviewed all changes and I approve them
[x] attach debdiff against the package in (old)stable
[x] the issue is verified as fixed in unstable
[ Changes ]
Backport patch for CVE-2025-64329: a malicious user can exhaust memory
on the host by exploiting a bug in the CRI Attach implementation
(goroutine leaks).
Fix previous changelog entry (1.6.20~ds1-1+deb12u2).
Rename a patch that fixes a CVE with the name of the CVE itself, for
clarity.
Best,
Arnaud
diff -Nru containerd-1.6.20~ds1/debian/changelog
containerd-1.6.20~ds1/debian/changelog
--- containerd-1.6.20~ds1/debian/changelog 2025-11-17 04:57:18.000000000
+0700
+++ containerd-1.6.20~ds1/debian/changelog 2026-02-12 10:30:28.000000000
+0700
@@ -1,9 +1,19 @@
-containerd (1.6.20~ds1-1+deb12u2) bookworm-security; urgency=medium
+containerd (1.6.20~ds1-1+deb12u3) bookworm; urgency=medium
- * Fix overly broad directory permissions, Fixes: CVE-2024-25621
+ * Non-maintainer upload.
+ * Rename Fix-directory-permissions patch for clarity
* Fix bug in the CRI Attach implementation, Fixes: CVE-2025-64329
Closes: #1120343
+ -- Arnaud Rebillout <[email protected]> Thu, 12 Feb 2026 10:30:28 +0700
+
+containerd (1.6.20~ds1-1+deb12u2) bookworm-security; urgency=medium
+
+ * Fix overly broad directory permissions, Fixes: CVE-2024-25621
+ Closes: #1120285
+ * Fix large UID:GID (> 32bit) overflow, Fixes: CVE-2024-40635
+ Closes: #1100806
+
-- Reinhard Tartler <[email protected]> Sun, 16 Nov 2025 16:57:18 -0500
containerd (1.6.20~ds1-1+deb12u1) bookworm; urgency=medium
diff -Nru containerd-1.6.20~ds1/debian/gbp.conf
containerd-1.6.20~ds1/debian/gbp.conf
--- containerd-1.6.20~ds1/debian/gbp.conf 2025-11-17 04:57:18.000000000
+0700
+++ containerd-1.6.20~ds1/debian/gbp.conf 2026-02-12 10:30:28.000000000
+0700
@@ -1,5 +1,5 @@
[DEFAULT]
pristine-tar = True
-debian-branch = debian/sid
+debian-branch = debian/bookworm
upstream-branch = upstream/sid
dist = DEP14
diff -Nru containerd-1.6.20~ds1/debian/patches/0012-CVE-2024-25621.patch
containerd-1.6.20~ds1/debian/patches/0012-CVE-2024-25621.patch
--- containerd-1.6.20~ds1/debian/patches/0012-CVE-2024-25621.patch
1970-01-01 08:00:00.000000000 +0800
+++ containerd-1.6.20~ds1/debian/patches/0012-CVE-2024-25621.patch
2026-02-12 10:30:28.000000000 +0700
@@ -0,0 +1,95 @@
+From: Akihiro Suda <[email protected]>
+Date: Mon, 27 Oct 2025 16:42:59 +0900
+Subject: 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/<NS>/<ID> 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 <[email protected]>
+(cherry picked from commit 51b0cf11dc5af7ed1919beba259e644138b28d96)
+Signed-off-by: Akihiro Suda <[email protected]>
+---
+ pkg/cri/cri.go | 7 +++++++
+ runtime/v2/manager.go | 2 ++
+ services/server/server.go | 14 ++++++++++++--
+ 3 files changed, 21 insertions(+), 2 deletions(-)
+
+Index: containerd/pkg/cri/cri.go
+===================================================================
+--- containerd.orig/pkg/cri/cri.go
++++ containerd/pkg/cri/cri.go
+@@ -19,6 +19,7 @@ package cri
+ import (
+ "flag"
+ "fmt"
++ "os"
+ "path/filepath"
+
+ "github.com/containerd/containerd"
+@@ -68,6 +69,13 @@ func initCRIService(ic *plugin.InitConte
+ return nil, fmt.Errorf("invalid plugin config: %w", err)
+ }
+
++ if err := os.MkdirAll(ic.State, 0700); err != nil {
++ return nil, err
++ }
++ // chmod is needed for upgrading from an older release that created the
dir with 0755
++ if err := os.Chmod(ic.State, 0700); err != nil {
++ return nil, err
++ }
+ c := criconfig.Config{
+ PluginConfig: *pluginConfig,
+ ContainerdRootDir: filepath.Dir(ic.Root),
+Index: containerd/runtime/v2/manager.go
+===================================================================
+--- containerd.orig/runtime/v2/manager.go
++++ containerd/runtime/v2/manager.go
+@@ -109,6 +109,8 @@ type ManagerConfig struct {
+ // NewShimManager creates a manager for v2 shims
+ func NewShimManager(ctx context.Context, config *ManagerConfig)
(*ShimManager, error) {
+ for _, d := range []string{config.Root, config.State} {
++ // root: the parent of this directory is created as 0700, not
0711.
++ // state: the parent of this directory is created as 0711 too,
so as to support userns-remapped containers.
+ if err := os.MkdirAll(d, 0711); err != nil {
+ return nil, err
+ }
+Index: containerd/services/server/server.go
+===================================================================
+--- containerd.orig/services/server/server.go
++++ containerd/services/server/server.go
+@@ -79,16 +79,26 @@ func CreateTopLevelDirectories(config *s
+ return errors.New("root and state must be different paths")
+ }
+
+- if err := sys.MkdirAllWithACL(config.Root, 0711); err != nil {
++ if err := sys.MkdirAllWithACL(config.Root, 0700); 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, 0700); 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, 0711); err != nil {
+ return err
+ }
+
+ if config.TempDir != "" {
+- if err := sys.MkdirAllWithACL(config.TempDir, 0711); err != nil
{
++ if err := sys.MkdirAllWithACL(config.TempDir, 0700); 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, 0700); err != nil {
+ return err
+ }
+ if runtime.GOOS == "windows" {
diff -Nru
containerd-1.6.20~ds1/debian/patches/0013-Fix-directory-permissions.patch
containerd-1.6.20~ds1/debian/patches/0013-Fix-directory-permissions.patch
--- containerd-1.6.20~ds1/debian/patches/0013-Fix-directory-permissions.patch
2025-11-17 04:57:18.000000000 +0700
+++ containerd-1.6.20~ds1/debian/patches/0013-Fix-directory-permissions.patch
1970-01-01 08:00:00.000000000 +0800
@@ -1,95 +0,0 @@
-From: Akihiro Suda <[email protected]>
-Date: Mon, 27 Oct 2025 16:42:59 +0900
-Subject: 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/<NS>/<ID> 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 <[email protected]>
-(cherry picked from commit 51b0cf11dc5af7ed1919beba259e644138b28d96)
-Signed-off-by: Akihiro Suda <[email protected]>
----
- pkg/cri/cri.go | 7 +++++++
- runtime/v2/manager.go | 2 ++
- services/server/server.go | 14 ++++++++++++--
- 3 files changed, 21 insertions(+), 2 deletions(-)
-
-Index: containerd/pkg/cri/cri.go
-===================================================================
---- containerd.orig/pkg/cri/cri.go
-+++ containerd/pkg/cri/cri.go
-@@ -19,6 +19,7 @@ package cri
- import (
- "flag"
- "fmt"
-+ "os"
- "path/filepath"
-
- "github.com/containerd/containerd"
-@@ -68,6 +69,13 @@ func initCRIService(ic *plugin.InitConte
- return nil, fmt.Errorf("invalid plugin config: %w", err)
- }
-
-+ if err := os.MkdirAll(ic.State, 0700); err != nil {
-+ return nil, err
-+ }
-+ // chmod is needed for upgrading from an older release that created the
dir with 0755
-+ if err := os.Chmod(ic.State, 0700); err != nil {
-+ return nil, err
-+ }
- c := criconfig.Config{
- PluginConfig: *pluginConfig,
- ContainerdRootDir: filepath.Dir(ic.Root),
-Index: containerd/runtime/v2/manager.go
-===================================================================
---- containerd.orig/runtime/v2/manager.go
-+++ containerd/runtime/v2/manager.go
-@@ -109,6 +109,8 @@ type ManagerConfig struct {
- // NewShimManager creates a manager for v2 shims
- func NewShimManager(ctx context.Context, config *ManagerConfig)
(*ShimManager, error) {
- for _, d := range []string{config.Root, config.State} {
-+ // root: the parent of this directory is created as 0700, not
0711.
-+ // state: the parent of this directory is created as 0711 too,
so as to support userns-remapped containers.
- if err := os.MkdirAll(d, 0711); err != nil {
- return nil, err
- }
-Index: containerd/services/server/server.go
-===================================================================
---- containerd.orig/services/server/server.go
-+++ containerd/services/server/server.go
-@@ -79,16 +79,26 @@ func CreateTopLevelDirectories(config *s
- return errors.New("root and state must be different paths")
- }
-
-- if err := sys.MkdirAllWithACL(config.Root, 0711); err != nil {
-+ if err := sys.MkdirAllWithACL(config.Root, 0700); 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, 0700); 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, 0711); err != nil {
- return err
- }
-
- if config.TempDir != "" {
-- if err := sys.MkdirAllWithACL(config.TempDir, 0711); err != nil
{
-+ if err := sys.MkdirAllWithACL(config.TempDir, 0700); 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, 0700); err != nil {
- return err
- }
- if runtime.GOOS == "windows" {
diff -Nru containerd-1.6.20~ds1/debian/patches/0014-CVE-2025-64329.patch
containerd-1.6.20~ds1/debian/patches/0014-CVE-2025-64329.patch
--- containerd-1.6.20~ds1/debian/patches/0014-CVE-2025-64329.patch
1970-01-01 08:00:00.000000000 +0800
+++ containerd-1.6.20~ds1/debian/patches/0014-CVE-2025-64329.patch
2026-02-12 10:30:28.000000000 +0700
@@ -0,0 +1,70 @@
+From: wheat2018 <[email protected]>
+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 <[email protected]>
+Signed-off-by: Akihiro Suda <[email protected]>
+(cherry picked from commit a0d0f0ef68935338d2c710db164fa7820f692530)
+Signed-off-by: Akihiro Suda <[email protected]>
+Origin: backport, https://github.com/containerd/containerd/c575d1b5
+---
+ pkg/cri/io/container_io.go | 14 +++++++++++---
+ pkg/cri/server/container_attach.go | 2 +-
+ 2 files changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/pkg/cri/io/container_io.go b/pkg/cri/io/container_io.go
+index 70bc8b7..e158410 100644
+--- a/pkg/cri/io/container_io.go
++++ b/pkg/cri/io/container_io.go
+@@ -17,6 +17,7 @@
+ package io
+
+ import (
++ "context"
+ "errors"
+ "io"
+ "strings"
+@@ -134,7 +135,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)
+@@ -175,8 +176,15 @@ func (c *ContainerIO) Attach(opts AttachOptions) {
+ }
+
+ attachStream := func(key string, close <-chan struct{}) {
+- <-close
+- logrus.Infof("Attach stream %q closed", key)
++ select {
++ case <-close:
++ logrus.Infof("Attach stream %q closed", key)
++ case <-ctx.Done():
++ logrus.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/pkg/cri/server/container_attach.go
b/pkg/cri/server/container_attach.go
+index a952150..3625229 100644
+--- a/pkg/cri/server/container_attach.go
++++ b/pkg/cri/server/container_attach.go
+@@ -79,6 +79,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
+ }
diff -Nru containerd-1.6.20~ds1/debian/patches/series
containerd-1.6.20~ds1/debian/patches/series
--- containerd-1.6.20~ds1/debian/patches/series 2025-11-17 04:57:18.000000000
+0700
+++ containerd-1.6.20~ds1/debian/patches/series 2026-02-12 10:30:28.000000000
+0700
@@ -7,5 +7,6 @@
0007-cri-fix-integration-test-on-cgroupsv2-system.patch
0008-Add-Debian-specific-CNI-bin-dir-to-ctr-run-command.patch
0011-allow-test-run-in-userns.patch
+0012-CVE-2024-25621.patch
0013-CVE-2024-40635.patch
-0013-Fix-directory-permissions.patch
+0014-CVE-2025-64329.patch