Compare commits

3 Commits
main ... 1.1

15 changed files with 1965 additions and 18252 deletions

View File

@@ -0,0 +1,135 @@
From 172170d06ef6c5ecbe19db448284a8c8c732ed15 Mon Sep 17 00:00:00 2001
From: Danish Prakash <contact@danishpraka.sh>
Date: Thu, 13 Mar 2025 14:37:38 +0530
Subject: [PATCH 1/4] CVE-2025-22869: ssh: limit the size of the internal
packet queue while waiting for KEX (#13)
In the SSH protocol, clients and servers execute the key exchange to
generate one-time session keys used for encryption and authentication.
The key exchange is performed initially after the connection is
established and then periodically after a configurable amount of data.
While a key exchange is in progress, we add the received packets to an
internal queue until we receive SSH_MSG_KEXINIT from the other side.
This can result in high memory usage if the other party is slow to
respond to the SSH_MSG_KEXINIT packet, or memory exhaustion if a
malicious client never responds to an SSH_MSG_KEXINIT packet during a
large file transfer.
We now limit the internal queue to 64 packets: this means 2MB with the
typical 32KB packet size.
When the internal queue is full we block further writes until the
pending key exchange is completed or there is a read or write error.
Thanks to Yuichi Watanabe for reporting this issue.
Fixes: CVE-2025-22869
Bugs: bsc#1239330
Signed-off-by: Danish Prakash <contact@danishpraka.sh>
Co-authored-by: Nicola Murino <nicola.murino@gmail.com>
---
vendor/golang.org/x/crypto/ssh/handshake.go | 47 ++++++++++++++++-----
1 file changed, 37 insertions(+), 10 deletions(-)
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
index 56cdc7c21c3b..a68d20f7f396 100644
--- a/vendor/golang.org/x/crypto/ssh/handshake.go
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -25,6 +25,11 @@ const debugHandshake = false
// quickly.
const chanSize = 16
+// maxPendingPackets sets the maximum number of packets to queue while waiting
+// for KEX to complete. This limits the total pending data to maxPendingPackets
+// * maxPacket bytes, which is ~16.8MB.
+const maxPendingPackets = 64
+
// keyingTransport is a packet based transport that supports key
// changes. It need not be thread-safe. It should pass through
// msgNewKeys in both directions.
@@ -73,11 +78,19 @@ type handshakeTransport struct {
incoming chan []byte
readError error
- mu sync.Mutex
- writeError error
- sentInitPacket []byte
- sentInitMsg *kexInitMsg
- pendingPackets [][]byte // Used when a key exchange is in progress.
+ mu sync.Mutex
+ // Condition for the above mutex. It is used to notify a completed key
+ // exchange or a write failure. Writes can wait for this condition while a
+ // key exchange is in progress.
+ writeCond *sync.Cond
+ writeError error
+ sentInitPacket []byte
+ sentInitMsg *kexInitMsg
+ // Used to queue writes when a key exchange is in progress. The length is
+ // limited by pendingPacketsSize. Once full, writes will block until the key
+ // exchange is completed or an error occurs. If not empty, it is emptied
+ // all at once when the key exchange is completed in kexLoop.
+ pendingPackets [][]byte
writePacketsLeft uint32
writeBytesLeft int64
@@ -133,6 +146,7 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion,
config: config,
}
+ t.writeCond = sync.NewCond(&t.mu)
t.resetReadThresholds()
t.resetWriteThresholds()
@@ -259,6 +273,7 @@ func (t *handshakeTransport) recordWriteError(err error) {
defer t.mu.Unlock()
if t.writeError == nil && err != nil {
t.writeError = err
+ t.writeCond.Broadcast()
}
}
@@ -362,6 +377,8 @@ write:
}
}
t.pendingPackets = t.pendingPackets[:0]
+ // Unblock writePacket if waiting for KEX.
+ t.writeCond.Broadcast()
t.mu.Unlock()
}
@@ -567,11 +584,20 @@ func (t *handshakeTransport) writePacket(p []byte) error {
}
if t.sentInitMsg != nil {
- // Copy the packet so the writer can reuse the buffer.
- cp := make([]byte, len(p))
- copy(cp, p)
- t.pendingPackets = append(t.pendingPackets, cp)
- return nil
+ if len(t.pendingPackets) < maxPendingPackets {
+ // Copy the packet so the writer can reuse the buffer.
+ cp := make([]byte, len(p))
+ copy(cp, p)
+ t.pendingPackets = append(t.pendingPackets, cp)
+ return nil
+ }
+ for t.sentInitMsg != nil {
+ // Block and wait for KEX to complete or an error.
+ t.writeCond.Wait()
+ if t.writeError != nil {
+ return t.writeError
+ }
+ }
}
if t.writeBytesLeft > 0 {
@@ -588,6 +614,7 @@ func (t *handshakeTransport) writePacket(p []byte) error {
if err := t.pushPacket(p); err != nil {
t.writeError = err
+ t.writeCond.Broadcast()
}
return nil
--
2.51.0

View File

@@ -1,162 +0,0 @@
From 76fc90dd1b33fc4e0f70277430f56d1d0ecd5e45 Mon Sep 17 00:00:00 2001
From: Danish Prakash <contact@danishpraka.sh>
Date: Mon, 7 Oct 2024 14:03:25 +0530
Subject: [PATCH 1/4] pkg/subscriptions: use securejoin for the container path
If we join a path from the container image we must always use securejoin
to prevent us from following a symlink onto the host.
Fixes CVE-2024-9341
Bugs: bsc#1231230
Signed-off-by: Paul Holzinger <pholzing@redhat.com>
Signed-off-by: Danish Prakash <contact@danishpraka.sh>
---
go.mod | 4 ++--
go.sum | 8 ++++----
.../containers/common/pkg/subscriptions/subscriptions.go | 6 +++++-
vendor/github.com/containers/common/version/version.go | 2 +-
.../containers/image/v5/docker/docker_image.go | 9 +++++++++
vendor/github.com/containers/image/v5/version/version.go | 2 +-
vendor/modules.txt | 4 ++--
7 files changed, 24 insertions(+), 11 deletions(-)
diff --git a/go.mod b/go.mod
index 6f0d7d1f5db6..88dd9876472f 100644
--- a/go.mod
+++ b/go.mod
@@ -11,10 +11,10 @@ require (
github.com/checkpoint-restore/go-criu/v7 v7.0.0
github.com/containernetworking/plugins v1.4.0
github.com/containers/buildah v1.35.4
- github.com/containers/common v0.58.3
+ github.com/containers/common v0.58.5
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/gvisor-tap-vsock v0.7.3
- github.com/containers/image/v5 v5.30.1
+ github.com/containers/image/v5 v5.30.2
github.com/containers/libhvee v0.7.0
github.com/containers/ocicrypt v1.1.10
github.com/containers/psgo v1.9.0
diff --git a/go.sum b/go.sum
index b1033efba2f0..1d6b7d02370c 100644
--- a/go.sum
+++ b/go.sum
@@ -76,14 +76,14 @@ github.com/containernetworking/plugins v1.4.0 h1:+w22VPYgk7nQHw7KT92lsRmuToHvb7w
github.com/containernetworking/plugins v1.4.0/go.mod h1:UYhcOyjefnrQvKvmmyEKsUA+M9Nfn7tqULPpH0Pkcj0=
github.com/containers/buildah v1.35.4 h1:M/M5RJW07ZIDsngmJDb6bnWxZA2RRFulp0MW7EwPATg=
github.com/containers/buildah v1.35.4/go.mod h1:gh6xe/VXW7TTIDWCRtAvx0/YaNuEJWYabDKrHKj17So=
-github.com/containers/common v0.58.3 h1:Iy/CdYjluEK926QT+ejonz7YvoRHazeW7BAiLIkmUQ4=
-github.com/containers/common v0.58.3/go.mod h1:p4V1SNk+WOISgp01m+axuqCUxaDP3WSZPPzvnJnS/cQ=
+github.com/containers/common v0.58.5 h1:5GOyHhNPVeFEUFIxUmc0asO2X8NuErLpyrrpdDJq3v0=
+github.com/containers/common v0.58.5/go.mod h1:mlwmIzH9AOIxXpuKPmMd1N+zzoelRBddXKReRlHDSTU=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/gvisor-tap-vsock v0.7.3 h1:yORnf15sP+sLFhxLNLgmB5/lOhldn9dRMHx/tmYtSOQ=
github.com/containers/gvisor-tap-vsock v0.7.3/go.mod h1:NI1fLMtKXQZoDrrOeqryGz7x7j/XSFWRmQILva7Fu9c=
-github.com/containers/image/v5 v5.30.1 h1:AKrQMgOKI1oKx5FW5eoU2xoNyzACajHGx1O3qxobvFM=
-github.com/containers/image/v5 v5.30.1/go.mod h1:gSD8MVOyqBspc0ynLsuiMR9qmt8UQ4jpVImjmK0uXfk=
+github.com/containers/image/v5 v5.30.2 h1:1nsuEAkWtlaGaV938n5Z9eyV4Jolx4eRyOl9pLUSPC4=
+github.com/containers/image/v5 v5.30.2/go.mod h1:gSD8MVOyqBspc0ynLsuiMR9qmt8UQ4jpVImjmK0uXfk=
github.com/containers/libhvee v0.7.0 h1:TDfidZOduYk0ZW0tigzqpJOl+CeynvHxIZCuH/ak7YM=
github.com/containers/libhvee v0.7.0/go.mod h1:fRKB3AyIqHMvq6xaeYhTpckM2cdoq0oecolyoiuLP7M=
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA=
diff --git a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
index 6845914aa285..04cf6deaa8b4 100644
--- a/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
+++ b/vendor/github.com/containers/common/pkg/subscriptions/subscriptions.go
@@ -10,6 +10,7 @@ import (
"github.com/containers/common/pkg/umask"
"github.com/containers/storage/pkg/idtools"
+ securejoin "github.com/cyphar/filepath-securejoin"
rspec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/sirupsen/logrus"
@@ -345,7 +346,10 @@ func addFIPSModeSubscription(mounts *[]rspec.Mount, containerRunDir, mountPoint,
srcBackendDir := "/usr/share/crypto-policies/back-ends/FIPS"
destDir := "/etc/crypto-policies/back-ends"
- srcOnHost := filepath.Join(mountPoint, srcBackendDir)
+ srcOnHost, err := securejoin.SecureJoin(mountPoint, srcBackendDir)
+ if err != nil {
+ return fmt.Errorf("resolve %s in the container: %w", srcBackendDir, err)
+ }
if _, err := os.Stat(srcOnHost); err != nil {
if errors.Is(err, os.ErrNotExist) {
return nil
diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go
index ddf29b94b366..1b8f07ff5659 100644
--- a/vendor/github.com/containers/common/version/version.go
+++ b/vendor/github.com/containers/common/version/version.go
@@ -1,4 +1,4 @@
package version
// Version is the version of the build.
-const Version = "0.58.3"
+const Version = "0.58.5"
diff --git a/vendor/github.com/containers/image/v5/docker/docker_image.go b/vendor/github.com/containers/image/v5/docker/docker_image.go
index 4c80bb2b5251..9741afc3f099 100644
--- a/vendor/github.com/containers/image/v5/docker/docker_image.go
+++ b/vendor/github.com/containers/image/v5/docker/docker_image.go
@@ -14,6 +14,7 @@ import (
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/types"
"github.com/opencontainers/go-digest"
+ "github.com/sirupsen/logrus"
)
// Image is a Docker-specific implementation of types.ImageCloser with a few extra methods
@@ -90,6 +91,14 @@ func GetRepositoryTags(ctx context.Context, sys *types.SystemContext, ref types.
}
for _, tag := range tagsHolder.Tags {
if _, err := reference.WithTag(dr.ref, tag); err != nil { // Ensure the tag does not contain unexpected values
+ // Per https://github.com/containers/skopeo/issues/2346 , unknown versions of JFrog Artifactory,
+ // contrary to the tag format specified in
+ // https://github.com/opencontainers/distribution-spec/blob/8a871c8234977df058f1a14e299fe0a673853da2/spec.md?plain=1#L160 ,
+ // include digests in the list.
+ if _, err := digest.Parse(tag); err == nil {
+ logrus.Debugf("Ignoring invalid tag %q matching a digest format", tag)
+ continue
+ }
return nil, fmt.Errorf("registry returned invalid tag %q: %w", tag, err)
}
tags = append(tags, tag)
diff --git a/vendor/github.com/containers/image/v5/version/version.go b/vendor/github.com/containers/image/v5/version/version.go
index 2be0541584da..fa31c9408f6a 100644
--- a/vendor/github.com/containers/image/v5/version/version.go
+++ b/vendor/github.com/containers/image/v5/version/version.go
@@ -8,7 +8,7 @@ const (
// VersionMinor is for functionality in a backwards-compatible manner
VersionMinor = 30
// VersionPatch is for backwards-compatible bug fixes
- VersionPatch = 1
+ VersionPatch = 2
// VersionDev indicates development branch. Releases will be empty string.
VersionDev = ""
diff --git a/vendor/modules.txt b/vendor/modules.txt
index ec7960bc9951..c4aad8b23ab0 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -171,7 +171,7 @@ github.com/containers/buildah/pkg/sshagent
github.com/containers/buildah/pkg/util
github.com/containers/buildah/pkg/volumes
github.com/containers/buildah/util
-# github.com/containers/common v0.58.3
+# github.com/containers/common v0.58.5
## explicit; go 1.20
github.com/containers/common/internal
github.com/containers/common/internal/attributedstring
@@ -243,7 +243,7 @@ github.com/containers/conmon/runner/config
# github.com/containers/gvisor-tap-vsock v0.7.3
## explicit; go 1.20
github.com/containers/gvisor-tap-vsock/pkg/types
-# github.com/containers/image/v5 v5.30.1
+# github.com/containers/image/v5 v5.30.2
## explicit; go 1.19
github.com/containers/image/v5/copy
github.com/containers/image/v5/directory
--
2.46.0

View File

@@ -1,49 +0,0 @@
From 5cc8b46f5e1df5a85ed7b037d6a31219bf58374c Mon Sep 17 00:00:00 2001
From: Danish Prakash <contact@danishpraka.sh>
Date: Wed, 16 Oct 2024 18:48:21 +0530
Subject: [PATCH 2/4] CVE-2024-9407: validate "bind-propagation" flag settings
CVE-2024-9407: validate that the value for the "bind-propagation" flag
when handling "bind" and "cache" mounts in `buildah run` or in RUN
instructions is one of the values that we would accept without the
"bind-propagation=" prefix.
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
Signed-off-by: Danish Prakash <contact@danishpraka.sh>
---
.../containers/buildah/internal/volumes/volumes.go | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/vendor/github.com/containers/buildah/internal/volumes/volumes.go b/vendor/github.com/containers/buildah/internal/volumes/volumes.go
index 515f846f3499..da6b768fdc21 100644
--- a/vendor/github.com/containers/buildah/internal/volumes/volumes.go
+++ b/vendor/github.com/containers/buildah/internal/volumes/volumes.go
@@ -105,6 +105,12 @@ func GetBindMount(ctx *types.SystemContext, args []string, contextDir string, st
if !hasArgValue {
return newMount, "", fmt.Errorf("%v: %w", argName, errBadOptionArg)
}
+ switch argValue {
+ default:
+ return newMount, "", fmt.Errorf("%v: %q: %w", argName, argValue, errBadMntOption)
+ case "shared", "rshared", "private", "rprivate", "slave", "rslave":
+ // this should be the relevant parts of the same list of options we accepted above
+ }
newMount.Options = append(newMount.Options, argValue)
case "src", "source":
if !hasArgValue {
@@ -277,6 +283,12 @@ func GetCacheMount(args []string, store storage.Store, imageMountLabel string, a
if !hasArgValue {
return newMount, nil, fmt.Errorf("%v: %w", argName, errBadOptionArg)
}
+ switch argValue {
+ default:
+ return newMount, nil, fmt.Errorf("%v: %q: %w", argName, argValue, errBadMntOption)
+ case "shared", "rshared", "private", "rprivate", "slave", "rslave":
+ // this should be the relevant parts of the same list of options we accepted above
+ }
newMount.Options = append(newMount.Options, argValue)
case "id":
if !hasArgValue {
--
2.46.0

View File

@@ -0,0 +1,59 @@
From 1207d8507d2567c890b552a9e156c8460b5fa477 Mon Sep 17 00:00:00 2001
From: rcmadhankumar <madhankumar.chellamuthu@suse.com>
Date: Mon, 12 May 2025 19:34:12 +0530
Subject: [PATCH 2/4] Fix: Remove appending rw as the default mount option
The backstory for this is that runc 1.2 (opencontainers/runc#3967)
fixed a long-standing bug in our mount flag handling (a bug that crun
still has). Before runc 1.2, when dealing with locked mount flags that
user namespaced containers cannot clear, trying to explicitly clearing
locked flags (like rw clearing MS_RDONLY) would silently ignore the rw
flag in most cases and would result in a read-only mount. This is
obviously not what the user expects.
What runc 1.2 did is that it made it so that passing clearing flags
like rw would always result in an attempt to clear the flag (which was
not the case before), and would (in all cases) explicitly return an
error if we try to clear locking flags. (This also let us finally fix a
bunch of other long-standing issues with locked mount flags causing
seemingly spurious errors).
The problem is that podman sets rw on all mounts by default (even if
the user doesn't specify anything). This is actually a no-op in
runc 1.1 and crun because of a bug in how clearing flags were handled
(rw is the absence of MS_RDONLY but until runc 1.2 we didn't correctly
track clearing flags like that, meaning that rw would literally be
handled as if it were not set at all by users) but in runc 1.2 leads to
unfortunate breakages and a subtle change in behaviour (before, a ro
mount being bind-mounted into a container would also be ro -- though
due to the above bug even setting rw explicitly would result in ro in
most cases -- but with runc 1.2 the mount will always be rw even if
the user didn't explicitly request it which most users would find
surprising). By the way, this "always set rw" behaviour is a departure
from Docker and it is not necesssary.
Bugs: bsc#1242132
Signed-off-by: rcmadhankumar <madhankumar.chellamuthu@suse.com>
Signed-off-by: Danish Prakash <contact@danishpraka.sh>
---
pkg/util/mount_opts.go | 3 ---
1 file changed, 3 deletions(-)
diff --git a/pkg/util/mount_opts.go b/pkg/util/mount_opts.go
index c9a773093e72..4e37fd74a0af 100644
--- a/pkg/util/mount_opts.go
+++ b/pkg/util/mount_opts.go
@@ -191,9 +191,6 @@ func processOptionsInternal(options []string, isTmpfs bool, sourcePath string, g
newOptions = append(newOptions, opt)
}
- if !foundWrite {
- newOptions = append(newOptions, "rw")
- }
if !foundProp {
if recursiveBind {
newOptions = append(newOptions, "rprivate")
--
2.51.0

View File

@@ -0,0 +1,57 @@
From 879b877db3607f50b8d1b30d096b1882b7aba65c Mon Sep 17 00:00:00 2001
From: Paul Holzinger <pholzing@redhat.com>
Date: Tue, 10 Jun 2025 14:16:46 +0200
Subject: [PATCH 3/4] CVE-2025-6032: machine init: fix tls check
Ensure we verify the TLS connection when pulling the OCI image.
Bugs: bsc#1245320
Fixes: CVE-2025-6032
Signed-off-by: Paul Holzinger <pholzing@redhat.com>
Signed-off-by: Danish Prakash <contact@danishpraka.sh>
---
pkg/machine/ocipull/ociartifact.go | 2 +-
pkg/machine/ocipull/pull.go | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/pkg/machine/ocipull/ociartifact.go b/pkg/machine/ocipull/ociartifact.go
index e144689ffe53..75154437e9ae 100644
--- a/pkg/machine/ocipull/ociartifact.go
+++ b/pkg/machine/ocipull/ociartifact.go
@@ -224,7 +224,7 @@ func (o *OCIArtifactDisk) getDestArtifact() (types.ImageReference, digest.Digest
}
fmt.Printf("Looking up Podman Machine image at %s to create VM\n", imgRef.DockerReference())
sysCtx := &types.SystemContext{
- DockerInsecureSkipTLSVerify: types.NewOptionalBool(!o.pullOptions.TLSVerify),
+ DockerInsecureSkipTLSVerify: o.pullOptions.SkipTLSVerify,
}
imgSrc, err := imgRef.NewImageSource(o.ctx, sysCtx)
if err != nil {
diff --git a/pkg/machine/ocipull/pull.go b/pkg/machine/ocipull/pull.go
index 0822578e8a96..85cf5c18ec73 100644
--- a/pkg/machine/ocipull/pull.go
+++ b/pkg/machine/ocipull/pull.go
@@ -21,8 +21,8 @@ import (
// PullOptions includes data to alter certain knobs when pulling a source
// image.
type PullOptions struct {
- // Require HTTPS and verify certificates when accessing the registry.
- TLSVerify bool
+ // Skip TLS verification when accessing the registry.
+ SkipTLSVerify types.OptionalBool
// [username[:password] to use when connecting to the registry.
Credentials string
// Quiet the progress bars when pushing.
@@ -46,7 +46,7 @@ func Pull(ctx context.Context, imageInput types.ImageReference, localDestPath *d
}
sysCtx := &types.SystemContext{
- DockerInsecureSkipTLSVerify: types.NewOptionalBool(!options.TLSVerify),
+ DockerInsecureSkipTLSVerify: options.SkipTLSVerify,
}
if options.Credentials != "" {
authConf, err := parse.AuthConfig(options.Credentials)
--
2.51.0

View File

@@ -1,68 +0,0 @@
From daca228525b387598a36d7de15a816ee8146b98d Mon Sep 17 00:00:00 2001
From: Danish Prakash <contact@danishpraka.sh>
Date: Tue, 15 Oct 2024 22:39:03 +0530
Subject: [PATCH 3/4] Properly validate cache IDs and sources
The `--mount type=cache` argument to the `RUN` instruction in
Dockerfiles was using `filepath.Join` on user input, allowing
crafted paths to be used to gain access to paths on the host,
when the command should normally be limited only to Buildah;s own
cache and context directories. Switch to `filepath.SecureJoin` to
resolve the issue.
Fixes CVE-2024-9675
Signed-off-by: Matt Heon <mheon@redhat.com>
Signed-off-by: Danish Prakash <contact@danishpraka.sh>
---
.../buildah/internal/volumes/volumes.go | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/vendor/github.com/containers/buildah/internal/volumes/volumes.go b/vendor/github.com/containers/buildah/internal/volumes/volumes.go
index da6b768fdc21..610e9fcf11b2 100644
--- a/vendor/github.com/containers/buildah/internal/volumes/volumes.go
+++ b/vendor/github.com/containers/buildah/internal/volumes/volumes.go
@@ -23,6 +23,7 @@ import (
"github.com/containers/storage/pkg/idtools"
"github.com/containers/storage/pkg/lockfile"
"github.com/containers/storage/pkg/unshare"
+ digest "github.com/opencontainers/go-digest"
specs "github.com/opencontainers/runtime-spec/specs-go"
selinux "github.com/opencontainers/selinux/go-selinux"
)
@@ -374,7 +375,11 @@ func GetCacheMount(args []string, store storage.Store, imageMountLabel string, a
return newMount, nil, fmt.Errorf("no stage found with name %s", fromStage)
}
// path should be /contextDir/specified path
- newMount.Source = filepath.Join(mountPoint, filepath.Clean(string(filepath.Separator)+newMount.Source))
+ evaluated, err := copier.Eval(mountPoint, string(filepath.Separator)+newMount.Source, copier.EvalOptions{})
+ if err != nil {
+ return newMount, nil, err
+ }
+ newMount.Source = evaluated
} else {
// we need to create cache on host if no image is being used
@@ -391,11 +396,15 @@ func GetCacheMount(args []string, store storage.Store, imageMountLabel string, a
}
if id != "" {
- newMount.Source = filepath.Join(cacheParent, filepath.Clean(id))
- buildahLockFilesDir = filepath.Join(BuildahCacheLockfileDir, filepath.Clean(id))
+ // Don't let the user control where we place the directory.
+ dirID := digest.FromString(id).Encoded()[:16]
+ newMount.Source = filepath.Join(cacheParent, dirID)
+ buildahLockFilesDir = filepath.Join(BuildahCacheLockfileDir, dirID)
} else {
- newMount.Source = filepath.Join(cacheParent, filepath.Clean(newMount.Destination))
- buildahLockFilesDir = filepath.Join(BuildahCacheLockfileDir, filepath.Clean(newMount.Destination))
+ // Don't let the user control where we place the directory.
+ dirID := digest.FromString(newMount.Destination).Encoded()[:16]
+ newMount.Source = filepath.Join(cacheParent, dirID)
+ buildahLockFilesDir = filepath.Join(BuildahCacheLockfileDir, dirID)
}
idPair := idtools.IDPair{
UID: uid,
--
2.46.0

View File

@@ -0,0 +1,148 @@
From 086fcc6cb3ba901873bd8d300c241be264517fe3 Mon Sep 17 00:00:00 2001
From: Paul Holzinger <pholzing@redhat.com>
Date: Fri, 29 Aug 2025 15:39:38 +0200
Subject: [PATCH 4/4] CVE-2025-9566: kube play: don't follow volume symlinks
onto the host
For ConfigMap and Secret kube play volumes podman populates the data
from the yaml. However the volume content is not controlled by us and we
can be tricked following a symlink to a file on the host instead.
Bugs: bsc#1249154
Fixes: CVE-2025-9566
Signed-off-by: Paul Holzinger <pholzing@redhat.com>
Signed-off-by: tomsweeneyredhat <tsweeney@redhat.com>
Signed-off-by: Danish Prakash <contact@danishpraka.sh>
---
pkg/domain/infra/abi/play.go | 5 ++-
pkg/domain/infra/abi/play_linux.go | 18 +++++++++++
pkg/domain/infra/abi/play_unsupported.go | 13 ++++++++
pkg/domain/infra/abi/play_utils.go | 39 +++++++++++++++++++++++-
4 files changed, 71 insertions(+), 4 deletions(-)
create mode 100644 pkg/domain/infra/abi/play_linux.go
create mode 100644 pkg/domain/infra/abi/play_unsupported.go
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index 6ffbf4cf54e6..2fa2752d7cda 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -808,8 +808,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
defaultMode := v.DefaultMode
// Create files and add data to the volume mountpoint based on the Items in the volume
for k, v := range v.Items {
- dataPath := filepath.Join(mountPoint, k)
- f, err := os.Create(dataPath)
+ f, err := openPathSafely(mountPoint, k)
if err != nil {
return nil, nil, fmt.Errorf("cannot create file %q at volume mountpoint %q: %w", k, mountPoint, err)
}
@@ -819,7 +818,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
return nil, nil, err
}
// Set file permissions
- if err := os.Chmod(f.Name(), os.FileMode(defaultMode)); err != nil {
+ if err := f.Chmod(os.FileMode(defaultMode)); err != nil {
return nil, nil, err
}
}
diff --git a/pkg/domain/infra/abi/play_linux.go b/pkg/domain/infra/abi/play_linux.go
new file mode 100644
index 000000000000..a0f981151669
--- /dev/null
+++ b/pkg/domain/infra/abi/play_linux.go
@@ -0,0 +1,18 @@
+//go:build !remote
+
+package abi
+
+import (
+ "os"
+
+ securejoin "github.com/cyphar/filepath-securejoin"
+)
+
+// openSymlinkPath opens the path under root using securejoin.OpenatInRoot().
+func openSymlinkPath(root *os.File, unsafePath string, flags int) (*os.File, error) {
+ file, err := securejoin.OpenatInRoot(root, unsafePath)
+ if err != nil {
+ return nil, err
+ }
+ return securejoin.Reopen(file, flags)
+}
diff --git a/pkg/domain/infra/abi/play_unsupported.go b/pkg/domain/infra/abi/play_unsupported.go
new file mode 100644
index 000000000000..3ecbae7cc1f6
--- /dev/null
+++ b/pkg/domain/infra/abi/play_unsupported.go
@@ -0,0 +1,13 @@
+//go:build !linux && !remote
+
+package abi
+
+import (
+ "errors"
+ "os"
+)
+
+// openSymlinkPath is not supported on this platform.
+func openSymlinkPath(root *os.File, unsafePath string, flags int) (*os.File, error) {
+ return nil, errors.New("cannot safely open symlink on this platform")
+}
diff --git a/pkg/domain/infra/abi/play_utils.go b/pkg/domain/infra/abi/play_utils.go
index 7285d9c9b987..217b6569972a 100644
--- a/pkg/domain/infra/abi/play_utils.go
+++ b/pkg/domain/infra/abi/play_utils.go
@@ -2,7 +2,14 @@
package abi
-import "github.com/containers/podman/v5/libpod/define"
+import (
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/containers/podman/v5/libpod/define"
+ "golang.org/x/sys/unix"
+)
// getSdNotifyMode returns the `sdNotifyAnnotation/$name` for the specified
// name. If name is empty, it'll only look for `sdNotifyAnnotation`.
@@ -16,3 +23,33 @@ func getSdNotifyMode(annotations map[string]string, name string) (string, error)
}
return mode, define.ValidateSdNotifyMode(mode)
}
+
+// openPathSafely opens the given name under the trusted root path, the unsafeName
+// must be a single path component and not contain "/".
+// The resulting path will be opened or created if it does not exists.
+// Following of symlink is done within staying under root, escapes outsides
+// of root are not allowed and prevent.
+//
+// This custom function is needed because securejoin.SecureJoin() is not race safe
+// and the volume might be mounted in another container that could swap in a symlink
+// after the function ahs run. securejoin.OpenInRoot() doesn't work either because
+// it cannot create files and doesn't work on freebsd.
+func openPathSafely(root, unsafeName string) (*os.File, error) {
+ if strings.Contains(unsafeName, "/") {
+ return nil, fmt.Errorf("name %q must not contain path separator", unsafeName)
+ }
+ fdDir, err := os.OpenFile(root, unix.O_RDONLY, 0)
+ if err != nil {
+ return nil, err
+ }
+ defer fdDir.Close()
+ flags := unix.O_CREAT | unix.O_WRONLY | unix.O_TRUNC | unix.O_CLOEXEC
+ fd, err := unix.Openat(int(fdDir.Fd()), unsafeName, flags|unix.O_NOFOLLOW, 0o644)
+ if err == nil {
+ return os.NewFile(uintptr(fd), unsafeName), nil
+ }
+ if err == unix.ELOOP {
+ return openSymlinkPath(fdDir, unsafeName, flags)
+ }
+ return nil, &os.PathError{Op: "openat", Path: unsafeName, Err: err}
+}
--
2.51.0

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
<service name="obs_scm" mode="manual">
<param name="url">https://github.com/containers/podman.git</param>
<param name="scm">git</param>
<param name="revision">v5.0.3</param>
<param name="revision">v5.4.2</param>
<param name="versionformat">@PARENT_TAG@</param>
<param name="changesgenerate">enable</param>
<param name="versionrewrite-pattern">v(.*)</param>

View File

@@ -1,4 +1,4 @@
<servicedata>
<service name="tar_scm">
<param name="url">https://github.com/containers/podman.git</param>
<param name="changesrevision">d08315df35cb6e95f65bf3935f529295c6e54742</param></service></servicedata>
<param name="changesrevision">be85287fcf4590961614ee37be65eeb315e5d9ff</param></service></servicedata>

Binary file not shown.

BIN
podman-5.4.2.obscpio LFS Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
name: podman
version: 5.0.3
mtime: 1715355434
commit: d08315df35cb6e95f65bf3935f529295c6e54742
version: 5.4.2
mtime: 1743601389
commit: be85287fcf4590961614ee37be65eeb315e5d9ff

View File

@@ -22,7 +22,7 @@
%bcond_without apparmor
Name: podman
Version: 5.0.3
Version: 5.4.2
Release: 0
Summary: Daemon-less container engine for managing containers, pods and images
License: Apache-2.0
@@ -30,10 +30,10 @@ Group: System/Management
URL: https://%{project}
Source0: %{name}-%{version}.tar.gz
Source1: podman.conf
Patch0: 0001-pkg-subscriptions-use-securejoin-for-the-container-p.patch
Patch1: 0002-CVE-2024-9407-validate-bind-propagation-flag-setting.patch
Patch2: 0003-Properly-validate-cache-IDs-and-sources.patch
Patch3: 0004-Use-securejoin.SecureJoin-when-forming-userns-paths.patch
Patch0: 0001-CVE-2025-22869-ssh-limit-the-size-of-the-internal-pa.patch
Patch1: 0002-Fix-Remove-appending-rw-as-the-default-mount-option.patch
Patch2: 0003-CVE-2025-6032-machine-init-fix-tls-check.patch
Patch3: 0004-CVE-2025-9566-kube-play-don-t-follow-volume-symlinks.patch
BuildRequires: bash-completion
BuildRequires: device-mapper-devel
BuildRequires: fdupes
@@ -65,9 +65,8 @@ Recommends: gvisor-tap-vsock
Requires: catatonit >= 0.1.7
Requires: conmon >= 2.0.24
Requires: fuse-overlayfs
Requires: iptables
Requires: libcontainers-common >= 20230214
%if 0%{?sle_version} && 0%{?sle_version} <= 150500
%if 0%{?suse_version} && 0%{?suse_version} < 1600
# Build podman with CNI support for SLE-15-SP5 and lower
Requires: (netavark or cni-plugins)
# We still want users with fresh installation to start off
@@ -77,17 +76,7 @@ Suggests: netavark
%else
Requires: netavark
%endif
# use crun on Tumbleweed & ALP for WASM support
%if 0%{suse_version} >= 1600
# crun is only available for selected archs (because of criu)
%ifarch x86_64 aarch64 ppc64le armv7l armv7hl s390x
Requires: crun
%else
Requires: runc >= 1.0.1
%endif
%else
Requires: runc >= 1.0.1
%endif
Requires: passt
Requires: timezone
Suggests: katacontainers
@@ -143,7 +132,7 @@ Provides: %{name}-shell = %{version}
capabilities specified in user quadlets.
It is a symlink to %{_bindir}/%{name} and execs into the `%{name}sh` container
when `%{_bindir}/%{name}sh is set as a login shell or set as os.Args[0].
when `%{_bindir}/%{name}sh` is set as a login shell or set as os.Args[0].
%build
# Build podman
@@ -196,6 +185,7 @@ install -m 0644 -t %{buildroot}%{_prefix}/lib/modules-load.d/ %{SOURCE1}
%{_mandir}/man1/podman*.1*
%{_mandir}/man5/podman*.5*
%{_mandir}/man5/quadlet*.5*
%{_mandir}/man7/podman*.7*
%exclude %{_mandir}/man1/podman-remote*.1*
# Configs
%dir %{_prefix}/lib/modules-load.d
@@ -218,12 +208,14 @@ install -m 0644 -t %{buildroot}%{_prefix}/lib/modules-load.d/ %{SOURCE1}
%{_unitdir}/podman-restart.service
%{_unitdir}/podman-auto-update.timer
%{_unitdir}/podman-clean-transient.service
%{_userunitdir}/podman-user-wait-network-online.service
%{_userunitdir}/podman.service
%{_userunitdir}/podman.socket
%{_userunitdir}/podman-auto-update.service
%{_userunitdir}/podman-kube@.service
%{_userunitdir}/podman-restart.service
%{_userunitdir}/podman-auto-update.timer
%{_userunitdir}/podman-clean-transient.service
%{_systemdusergeneratordir}/podman-user-generator
%{_systemdgeneratordir}/podman-system-generator
%ghost /run/podman
@@ -257,18 +249,19 @@ install -m 0644 -t %{buildroot}%{_prefix}/lib/modules-load.d/ %{SOURCE1}
%pre
%service_add_pre podman.service podman.socket podman-auto-update.service podman-restart.service podman-auto-update.timer podman-clean-transient.service
%systemd_user_pre podman.service podman.socket podman-auto-update.service podman-restart.service podman-auto-update.timer podman-clean-transient.service podman-user-wait-network-online.service
%post
%service_add_post podman.service podman.socket podman-auto-update.service podman-restart.service podman-auto-update.timer podman-clean-transient.service
%tmpfiles_create %{_tmpfilesdir}/podman.conf
%systemd_user_post podman.service podman.socket podman-auto-update.service podman-restart.service podman-auto-update.timer
%systemd_user_post podman.service podman.socket podman-auto-update.service podman-restart.service podman-auto-update.timer podman-clean-transient.service podman-user-wait-network-online.service
%preun
%service_del_preun podman.service podman.socket podman-auto-update.service podman-restart.service podman-auto-update.timer podman-clean-transient.service
%systemd_user_preun podman.service podman.socket podman-auto-update.service podman-restart.service podman-auto-update.timer
%systemd_user_preun podman.service podman.socket podman-auto-update.service podman-restart.service podman-auto-update.timer podman-clean-transient.service podman-user-wait-network-online.service
%postun
%service_del_postun podman.service podman.socket podman-auto-update.service podman-restart.service podman-auto-update.timer podman-clean-transient.service
%systemd_user_postun podman.service podman.socket podman-auto-update.service podman-restart.service podman-auto-update.timer
%systemd_user_postun podman.service podman.socket podman-auto-update.service podman-restart.service podman-auto-update.timer podman-clean-transient.service podman-user-wait-network-online.service
%changelog