summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--recipes-containers/podman/podman/CVE-2025-9566.patch152
-rw-r--r--recipes-containers/podman/podman_git.bb1
2 files changed, 153 insertions, 0 deletions
diff --git a/recipes-containers/podman/podman/CVE-2025-9566.patch b/recipes-containers/podman/podman/CVE-2025-9566.patch
new file mode 100644
index 00000000..7e5cbe8b
--- /dev/null
+++ b/recipes-containers/podman/podman/CVE-2025-9566.patch
@@ -0,0 +1,152 @@
1From ca994186f07822b9048fe711b6903e51614d3e15 Mon Sep 17 00:00:00 2001
2From: Paul Holzinger <pholzing@redhat.com>
3Date: Fri, 29 Aug 2025 15:39:38 +0200
4Subject: [PATCH] kube play: don't follow volume symlinks onto the host
5
6For ConfigMap and Secret kube play volumes podman populates the data
7from the yaml. However the volume content is not controlled by us and we
8can be tricked following a symlink to a file on the host instead.
9
10Fixes: CVE-2025-9566
11
12Signed-off-by: Paul Holzinger <pholzing@redhat.com>
13(cherry picked from commit 43fbde4e665fe6cee6921868f04b7ccd3de5ad89)
14Signed-off-by: Paul Holzinger <pholzing@redhat.com>
15
16CVE: CVE-2025-9566
17
18Upstream-Status: Backport [https://github.com/containers/podman/commit/ca994186f07822b9048fe711b6903e51614d3e15]
19
20Signed-off-by: Divya Chellam <divya.chellam@windriver.com>
21---
22 pkg/domain/infra/abi/play.go | 5 ++-
23 pkg/domain/infra/abi/play_linux.go | 18 +++++++++++
24 pkg/domain/infra/abi/play_unsupported.go | 13 ++++++++
25 pkg/domain/infra/abi/play_utils.go | 39 +++++++++++++++++++++++-
26 4 files changed, 71 insertions(+), 4 deletions(-)
27 create mode 100644 pkg/domain/infra/abi/play_linux.go
28 create mode 100644 pkg/domain/infra/abi/play_unsupported.go
29
30diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
31index 6ffbf4cf54..2fa2752d7c 100644
32--- a/pkg/domain/infra/abi/play.go
33+++ b/pkg/domain/infra/abi/play.go
34@@ -808,8 +808,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
35 defaultMode := v.DefaultMode
36 // Create files and add data to the volume mountpoint based on the Items in the volume
37 for k, v := range v.Items {
38- dataPath := filepath.Join(mountPoint, k)
39- f, err := os.Create(dataPath)
40+ f, err := openPathSafely(mountPoint, k)
41 if err != nil {
42 return nil, nil, fmt.Errorf("cannot create file %q at volume mountpoint %q: %w", k, mountPoint, err)
43 }
44@@ -819,7 +818,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
45 return nil, nil, err
46 }
47 // Set file permissions
48- if err := os.Chmod(f.Name(), os.FileMode(defaultMode)); err != nil {
49+ if err := f.Chmod(os.FileMode(defaultMode)); err != nil {
50 return nil, nil, err
51 }
52 }
53diff --git a/pkg/domain/infra/abi/play_linux.go b/pkg/domain/infra/abi/play_linux.go
54new file mode 100644
55index 0000000000..a0f9811516
56--- /dev/null
57+++ b/pkg/domain/infra/abi/play_linux.go
58@@ -0,0 +1,18 @@
59+//go:build !remote
60+
61+package abi
62+
63+import (
64+ "os"
65+
66+ securejoin "github.com/cyphar/filepath-securejoin"
67+)
68+
69+// openSymlinkPath opens the path under root using securejoin.OpenatInRoot().
70+func openSymlinkPath(root *os.File, unsafePath string, flags int) (*os.File, error) {
71+ file, err := securejoin.OpenatInRoot(root, unsafePath)
72+ if err != nil {
73+ return nil, err
74+ }
75+ return securejoin.Reopen(file, flags)
76+}
77diff --git a/pkg/domain/infra/abi/play_unsupported.go b/pkg/domain/infra/abi/play_unsupported.go
78new file mode 100644
79index 0000000000..3ecbae7cc1
80--- /dev/null
81+++ b/pkg/domain/infra/abi/play_unsupported.go
82@@ -0,0 +1,13 @@
83+//go:build !linux && !remote
84+
85+package abi
86+
87+import (
88+ "errors"
89+ "os"
90+)
91+
92+// openSymlinkPath is not supported on this platform.
93+func openSymlinkPath(root *os.File, unsafePath string, flags int) (*os.File, error) {
94+ return nil, errors.New("cannot safely open symlink on this platform")
95+}
96diff --git a/pkg/domain/infra/abi/play_utils.go b/pkg/domain/infra/abi/play_utils.go
97index 7285d9c9b9..217b656997 100644
98--- a/pkg/domain/infra/abi/play_utils.go
99+++ b/pkg/domain/infra/abi/play_utils.go
100@@ -2,7 +2,14 @@
101
102 package abi
103
104-import "github.com/containers/podman/v5/libpod/define"
105+import (
106+ "fmt"
107+ "os"
108+ "strings"
109+
110+ "github.com/containers/podman/v5/libpod/define"
111+ "golang.org/x/sys/unix"
112+)
113
114 // getSdNotifyMode returns the `sdNotifyAnnotation/$name` for the specified
115 // name. If name is empty, it'll only look for `sdNotifyAnnotation`.
116@@ -16,3 +23,33 @@ func getSdNotifyMode(annotations map[string]string, name string) (string, error)
117 }
118 return mode, define.ValidateSdNotifyMode(mode)
119 }
120+
121+// openPathSafely opens the given name under the trusted root path, the unsafeName
122+// must be a single path component and not contain "/".
123+// The resulting path will be opened or created if it does not exists.
124+// Following of symlink is done within staying under root, escapes outsides
125+// of root are not allowed and prevent.
126+//
127+// This custom function is needed because securejoin.SecureJoin() is not race safe
128+// and the volume might be mounted in another container that could swap in a symlink
129+// after the function ahs run. securejoin.OpenInRoot() doesn't work either because
130+// it cannot create files and doesn't work on freebsd.
131+func openPathSafely(root, unsafeName string) (*os.File, error) {
132+ if strings.Contains(unsafeName, "/") {
133+ return nil, fmt.Errorf("name %q must not contain path separator", unsafeName)
134+ }
135+ fdDir, err := os.OpenFile(root, unix.O_RDONLY, 0)
136+ if err != nil {
137+ return nil, err
138+ }
139+ defer fdDir.Close()
140+ flags := unix.O_CREAT | unix.O_WRONLY | unix.O_TRUNC | unix.O_CLOEXEC
141+ fd, err := unix.Openat(int(fdDir.Fd()), unsafeName, flags|unix.O_NOFOLLOW, 0o644)
142+ if err == nil {
143+ return os.NewFile(uintptr(fd), unsafeName), nil
144+ }
145+ if err == unix.ELOOP {
146+ return openSymlinkPath(fdDir, unsafeName, flags)
147+ }
148+ return nil, &os.PathError{Op: "openat", Path: unsafeName, Err: err}
149+}
150--
1512.40.0
152
diff --git a/recipes-containers/podman/podman_git.bb b/recipes-containers/podman/podman_git.bb
index d98521ba..dbbe59c3 100644
--- a/recipes-containers/podman/podman_git.bb
+++ b/recipes-containers/podman/podman_git.bb
@@ -22,6 +22,7 @@ SRC_URI = " \
22 ${@bb.utils.contains('PACKAGECONFIG', 'rootless', 'file://50-podman-rootless.conf', '', d)} \ 22 ${@bb.utils.contains('PACKAGECONFIG', 'rootless', 'file://50-podman-rootless.conf', '', d)} \
23 file://run-ptest \ 23 file://run-ptest \
24 file://CVE-2025-6032.patch;patchdir=src/import \ 24 file://CVE-2025-6032.patch;patchdir=src/import \
25 file://CVE-2025-9566.patch;patchdir=src/import \
25" 26"
26 27
27LICENSE = "Apache-2.0" 28LICENSE = "Apache-2.0"