Skip to content

Commit 135f040

Browse files
[MEDIUM] patch containerd2 for CVE-2025-47291 (#13926)
Co-authored-by: Kanishk Bansal <103916909+Kanishk-Bansal@users.noreply.github.com>
1 parent e75cd05 commit 135f040

2 files changed

Lines changed: 225 additions & 1 deletion

File tree

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
From 0bb95c53ec07aad729470844c8f0e5ab2838a8db Mon Sep 17 00:00:00 2001
2+
From: dj_palli <v-dpalli@microsoft.com>
3+
Date: Mon, 2 Jun 2025 14:45:30 +0000
4+
Subject: [PATCH] Address CVE-2025-47291
5+
6+
Upstream patch URL : https://github.com/containerd/containerd/commit/ec3567d6b369cde39739b41db8763a19d6f35c39
7+
8+
---
9+
client/container.go | 3 ++-
10+
client/task.go | 27 ++++++++++++++++++++++
11+
client/task_opts.go | 27 ++++++++--------------
12+
client/task_opts_unix.go | 48 +++++++++++++---------------------------
13+
4 files changed, 53 insertions(+), 52 deletions(-)
14+
15+
diff --git a/client/container.go b/client/container.go
16+
index b9cf25e..5763ae6 100644
17+
--- a/client/container.go
18+
+++ b/client/container.go
19+
@@ -279,7 +279,8 @@ func (c *container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...N
20+
}
21+
}
22+
info := TaskInfo{
23+
- runtime: r.Runtime.Name,
24+
+ runtime: r.Runtime.Name,
25+
+ runtimeOptions: r.Runtime.Options,
26+
}
27+
for _, o := range opts {
28+
if err := o(ctx, c.client, &info); err != nil {
29+
diff --git a/client/task.go b/client/task.go
30+
index 20312a9..152babe 100644
31+
--- a/client/task.go
32+
+++ b/client/task.go
33+
@@ -146,6 +146,10 @@ type TaskInfo struct {
34+
35+
// runtime is the runtime name for the container, and cannot be changed.
36+
runtime string
37+
+ // runtimeOptions is the runtime options for the container, and when task options are set,
38+
+ // they will be based on the runtimeOptions.
39+
+ // https://github.com/containerd/containerd/issues/11568
40+
+ runtimeOptions typeurl.Any
41+
}
42+
43+
// Runtime name for the container
44+
@@ -153,6 +157,29 @@ func (i *TaskInfo) Runtime() string {
45+
return i.runtime
46+
}
47+
48+
+// getRuncOptions returns a reference to the runtime options for use by the task.
49+
+// If the set of options is not set by the opts passed into the NewTask creation
50+
+// this function first attempts to initialize the runtime options with a copy of the runtimeOptions,
51+
+// otherwise an empty set of options is assigned and returned
52+
+func (i *TaskInfo) getRuncOptions() (*options.Options, error) {
53+
+ if i.Options != nil {
54+
+ opts, ok := i.Options.(*options.Options)
55+
+ if !ok {
56+
+ return nil, errors.New("invalid runtime v2 options format")
57+
+ }
58+
+ return opts, nil
59+
+ }
60+
+
61+
+ opts := &options.Options{}
62+
+ if i.runtimeOptions != nil && i.runtimeOptions.GetValue() != nil {
63+
+ if err := typeurl.UnmarshalTo(i.runtimeOptions, opts); err != nil {
64+
+ return nil, fmt.Errorf("failed to get runtime v2 options: %w", err)
65+
+ }
66+
+ }
67+
+ i.Options = opts
68+
+ return opts, nil
69+
+}
70+
+
71+
// Task is the executable object within containerd
72+
type Task interface {
73+
Process
74+
diff --git a/client/task_opts.go b/client/task_opts.go
75+
index 8e94d4c..27bde35 100644
76+
--- a/client/task_opts.go
77+
+++ b/client/task_opts.go
78+
@@ -54,12 +54,9 @@ func WithRuntimePath(absRuntimePath string) NewTaskOpts {
79+
// usually it is served inside a sandbox, and we can get it from sandbox status.
80+
func WithTaskAPIEndpoint(address string, version uint32) NewTaskOpts {
81+
return func(ctx context.Context, client *Client, info *TaskInfo) error {
82+
- if info.Options == nil {
83+
- info.Options = &options.Options{}
84+
- }
85+
- opts, ok := info.Options.(*options.Options)
86+
- if !ok {
87+
- return errors.New("invalid runtime v2 options format")
88+
+ opts, err := info.getRuncOptions()
89+
+ if err != nil {
90+
+ return err
91+
}
92+
opts.TaskApiAddress = address
93+
opts.TaskApiVersion = version
94+
@@ -119,12 +116,9 @@ func WithCheckpointImagePath(path string) CheckpointTaskOpts {
95+
// WithRestoreImagePath sets image path for create option
96+
func WithRestoreImagePath(path string) NewTaskOpts {
97+
return func(ctx context.Context, c *Client, ti *TaskInfo) error {
98+
- if ti.Options == nil {
99+
- ti.Options = &options.Options{}
100+
- }
101+
- opts, ok := ti.Options.(*options.Options)
102+
- if !ok {
103+
- return errors.New("invalid runtime v2 options format")
104+
+ opts, err := ti.getRuncOptions()
105+
+ if err != nil {
106+
+ return err
107+
}
108+
opts.CriuImagePath = path
109+
return nil
110+
@@ -134,12 +128,9 @@ func WithRestoreImagePath(path string) NewTaskOpts {
111+
// WithRestoreWorkPath sets criu work path for create option
112+
func WithRestoreWorkPath(path string) NewTaskOpts {
113+
return func(ctx context.Context, c *Client, ti *TaskInfo) error {
114+
- if ti.Options == nil {
115+
- ti.Options = &options.Options{}
116+
- }
117+
- opts, ok := ti.Options.(*options.Options)
118+
- if !ok {
119+
- return errors.New("invalid runtime v2 options format")
120+
+ opts, err := ti.getRuncOptions()
121+
+ if err != nil {
122+
+ return err
123+
}
124+
opts.CriuWorkPath = path
125+
return nil
126+
diff --git a/client/task_opts_unix.go b/client/task_opts_unix.go
127+
index d33e302..26b5c17 100644
128+
--- a/client/task_opts_unix.go
129+
+++ b/client/task_opts_unix.go
130+
@@ -20,20 +20,14 @@ package client
131+
132+
import (
133+
"context"
134+
- "errors"
135+
-
136+
- "github.com/containerd/containerd/api/types/runc/options"
137+
)
138+
139+
// WithNoNewKeyring causes tasks not to be created with a new keyring for secret storage.
140+
// There is an upper limit on the number of keyrings in a linux system
141+
func WithNoNewKeyring(ctx context.Context, c *Client, ti *TaskInfo) error {
142+
- if ti.Options == nil {
143+
- ti.Options = &options.Options{}
144+
- }
145+
- opts, ok := ti.Options.(*options.Options)
146+
- if !ok {
147+
- return errors.New("invalid v2 shim create options format")
148+
+ opts, err := ti.getRuncOptions()
149+
+ if err != nil {
150+
+ return err
151+
}
152+
opts.NoNewKeyring = true
153+
return nil
154+
@@ -41,12 +35,9 @@ func WithNoNewKeyring(ctx context.Context, c *Client, ti *TaskInfo) error {
155+
156+
// WithNoPivotRoot instructs the runtime not to you pivot_root
157+
func WithNoPivotRoot(_ context.Context, _ *Client, ti *TaskInfo) error {
158+
- if ti.Options == nil {
159+
- ti.Options = &options.Options{}
160+
- }
161+
- opts, ok := ti.Options.(*options.Options)
162+
- if !ok {
163+
- return errors.New("invalid v2 shim create options format")
164+
+ opts, err := ti.getRuncOptions()
165+
+ if err != nil {
166+
+ return err
167+
}
168+
opts.NoPivotRoot = true
169+
return nil
170+
@@ -55,12 +46,9 @@ func WithNoPivotRoot(_ context.Context, _ *Client, ti *TaskInfo) error {
171+
// WithShimCgroup sets the existing cgroup for the shim
172+
func WithShimCgroup(path string) NewTaskOpts {
173+
return func(ctx context.Context, c *Client, ti *TaskInfo) error {
174+
- if ti.Options == nil {
175+
- ti.Options = &options.Options{}
176+
- }
177+
- opts, ok := ti.Options.(*options.Options)
178+
- if !ok {
179+
- return errors.New("invalid v2 shim create options format")
180+
+ opts, err := ti.getRuncOptions()
181+
+ if err != nil {
182+
+ return err
183+
}
184+
opts.ShimCgroup = path
185+
return nil
186+
@@ -70,12 +58,9 @@ func WithShimCgroup(path string) NewTaskOpts {
187+
// WithUIDOwner allows console I/O to work with the remapped UID in user namespace
188+
func WithUIDOwner(uid uint32) NewTaskOpts {
189+
return func(ctx context.Context, c *Client, ti *TaskInfo) error {
190+
- if ti.Options == nil {
191+
- ti.Options = &options.Options{}
192+
- }
193+
- opts, ok := ti.Options.(*options.Options)
194+
- if !ok {
195+
- return errors.New("invalid v2 shim create options format")
196+
+ opts, err := ti.getRuncOptions()
197+
+ if err != nil {
198+
+ return err
199+
}
200+
opts.IoUid = uid
201+
return nil
202+
@@ -85,12 +70,9 @@ func WithUIDOwner(uid uint32) NewTaskOpts {
203+
// WithGIDOwner allows console I/O to work with the remapped GID in user namespace
204+
func WithGIDOwner(gid uint32) NewTaskOpts {
205+
return func(ctx context.Context, c *Client, ti *TaskInfo) error {
206+
- if ti.Options == nil {
207+
- ti.Options = &options.Options{}
208+
- }
209+
- opts, ok := ti.Options.(*options.Options)
210+
- if !ok {
211+
- return errors.New("invalid v2 shim create options format")
212+
+ opts, err := ti.getRuncOptions()
213+
+ if err != nil {
214+
+ return err
215+
}
216+
opts.IoGid = gid
217+
return nil
218+
--
219+
2.45.2
220+

SPECS/containerd2/containerd2.spec

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
Summary: Industry-standard container runtime
66
Name: %{upstream_name}2
77
Version: 2.0.0
8-
Release: 9%{?dist}
8+
Release: 10%{?dist}
99
License: ASL 2.0
1010
Group: Tools/Container
1111
URL: https://www.containerd.io
@@ -20,6 +20,7 @@ Patch0: CVE-2024-45338.patch
2020
Patch1: CVE-2025-27144.patch
2121
Patch2: CVE-2024-40635.patch
2222
Patch3: CVE-2025-22872.patch
23+
Patch4: CVE-2025-47291.patch
2324
%{?systemd_requires}
2425

2526
BuildRequires: golang
@@ -91,6 +92,9 @@ fi
9192
%dir /opt/containerd/lib
9293

9394
%changelog
95+
* Fri May 30 2025 Durga Jagadeesh Palli <v-dpalli@microsoft.com> - 2.0.0-10
96+
- Patch CVE-2025-47291
97+
9498
* Thu May 22 2025 Aninda Pradhan <v-anipradhan@microsoft.com> - 2.0.0-9
9599
- Patch CVE-2025-22872
96100

0 commit comments

Comments
 (0)