* [meta-virtualization][scarthgap][PATCH 2/3] buildah: fix CVE-2024-9676
2025-01-22 2:27 [meta-virtualization][scarthgap][PATCH 1/3] cri-o: update to 1.30.8 Qi.Chen
@ 2025-01-22 2:27 ` Qi.Chen
2025-01-22 2:27 ` [meta-virtualization][scarthgap][PATCH 3/3] podman: " Qi.Chen
2025-01-30 18:53 ` [meta-virtualization][scarthgap][PATCH 1/3] cri-o: update to 1.30.8 Bruce Ashfield
2 siblings, 0 replies; 4+ messages in thread
From: Qi.Chen @ 2025-01-22 2:27 UTC (permalink / raw)
To: meta-virtualization
From: Chen Qi <Qi.Chen@windriver.com>
Backport patch to fix CVE-2024-9676.
Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
---
...SecureJoin-when-forming-userns-paths.patch | 187 ++++++++++++++++++
recipes-containers/buildah/buildah_git.bb | 1 +
2 files changed, 188 insertions(+)
create mode 100644 recipes-containers/buildah/buildah/0001-Use-securejoin.SecureJoin-when-forming-userns-paths.patch
diff --git a/recipes-containers/buildah/buildah/0001-Use-securejoin.SecureJoin-when-forming-userns-paths.patch b/recipes-containers/buildah/buildah/0001-Use-securejoin.SecureJoin-when-forming-userns-paths.patch
new file mode 100644
index 00000000..73040e82
--- /dev/null
+++ b/recipes-containers/buildah/buildah/0001-Use-securejoin.SecureJoin-when-forming-userns-paths.patch
@@ -0,0 +1,187 @@
+From 854570c44c219c2b92b03b36b7a2069a32e2c08a Mon Sep 17 00:00:00 2001
+From: Matt Heon <mheon@redhat.com>
+Date: Wed, 9 Oct 2024 09:54:22 -0400
+Subject: [PATCH] Use securejoin.SecureJoin when forming userns paths
+
+We need to read /etc/passwd and /etc/group in the container to
+get an idea of how many UIDs and GIDs we need to allocate for a
+user namespace when `--userns=auto` is specified. We were forming
+paths for these using filepath.Join, which is not safe for paths
+within a container, resulting in this CVE allowing crafted
+symlinks in the container to access paths on the host instead.
+
+Cherry-pick conflict fixed for v1.51 branch, and converted to use
+the old securejoin API (securejoin.SecureJoin and then os.Open)
+as this branch is too old to have the new API.
+
+Addresses CVE-2024-9676
+
+Signed-off-by: Matt Heon <mheon@redhat.com>
+
+CVE: CVE-2024-9676
+
+Upstream-Status: Backport [854570c44c219c2b92b03b36b7a2069a32e2c08a]
+
+Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
+---
+ userns.go | 92 ++++++++++++++++++++++++++++++-------------
+ userns_unsupported.go | 14 +++++++
+ 2 files changed, 79 insertions(+), 27 deletions(-)
+ create mode 100644 userns_unsupported.go
+
+diff --git a/userns.go b/userns.go
+index 32ae830be..2c855da7c 100644
+--- a/userns.go
++++ b/userns.go
+@@ -1,18 +1,21 @@
++//go:build linux
++
+ package storage
+
+ import (
+ "fmt"
+ "os"
+ "os/user"
+- "path/filepath"
+ "strconv"
+
+ drivers "github.com/containers/storage/drivers"
+ "github.com/containers/storage/pkg/idtools"
+ "github.com/containers/storage/pkg/unshare"
+ "github.com/containers/storage/types"
++ securejoin "github.com/cyphar/filepath-securejoin"
+ libcontainerUser "github.com/opencontainers/runc/libcontainer/user"
+ "github.com/sirupsen/logrus"
++ "golang.org/x/sys/unix"
+ )
+
+ // getAdditionalSubIDs looks up the additional IDs configured for
+@@ -85,40 +88,59 @@ const nobodyUser = 65534
+ // parseMountedFiles returns the maximum UID and GID found in the /etc/passwd and
+ // /etc/group files.
+ func parseMountedFiles(containerMount, passwdFile, groupFile string) uint32 {
++ var (
++ passwd *os.File
++ group *os.File
++ size int
++ err error
++ )
+ if passwdFile == "" {
+- passwdFile = filepath.Join(containerMount, "etc/passwd")
+- }
+- if groupFile == "" {
+- groupFile = filepath.Join(groupFile, "etc/group")
++ passwd, err = secureOpen(containerMount, "/etc/passwd")
++ } else {
++ // User-specified override from a volume. Will not be in
++ // container root.
++ passwd, err = os.Open(passwdFile)
+ }
+-
+- size := 0
+-
+- users, err := libcontainerUser.ParsePasswdFile(passwdFile)
+ if err == nil {
+- for _, u := range users {
+- // Skip the "nobody" user otherwise we end up with 65536
+- // ids with most images
+- if u.Name == "nobody" {
+- continue
+- }
+- if u.Uid > size && u.Uid != nobodyUser {
+- size = u.Uid
+- }
+- if u.Gid > size && u.Gid != nobodyUser {
+- size = u.Gid
++ defer passwd.Close()
++
++ users, err := libcontainerUser.ParsePasswd(passwd)
++ if err == nil {
++ for _, u := range users {
++ // Skip the "nobody" user otherwise we end up with 65536
++ // ids with most images
++ if u.Name == "nobody" || u.Name == "nogroup" {
++ continue
++ }
++ if u.Uid > size && u.Uid != nobodyUser {
++ size = u.Uid + 1
++ }
++ if u.Gid > size && u.Gid != nobodyUser {
++ size = u.Gid + 1
++ }
+ }
+ }
+ }
+
+- groups, err := libcontainerUser.ParseGroupFile(groupFile)
++ if groupFile == "" {
++ group, err = secureOpen(containerMount, "/etc/group")
++ } else {
++ // User-specified override from a volume. Will not be in
++ // container root.
++ group, err = os.Open(groupFile)
++ }
+ if err == nil {
+- for _, g := range groups {
+- if g.Name == "nobody" {
+- continue
+- }
+- if g.Gid > size && g.Gid != nobodyUser {
+- size = g.Gid
++ defer group.Close()
++
++ groups, err := libcontainerUser.ParseGroup(group)
++ if err == nil {
++ for _, g := range groups {
++ if g.Name == "nobody" || g.Name == "nogroup" {
++ continue
++ }
++ if g.Gid > size && g.Gid != nobodyUser {
++ size = g.Gid + 1
++ }
+ }
+ }
+ }
+@@ -309,3 +331,19 @@ func getAutoUserNSIDMappings(
+ gidMap := append(availableGIDs.zip(requestedContainerGIDs), additionalGIDMappings...)
+ return uidMap, gidMap, nil
+ }
++
++// Securely open (read-only) a file in a container mount.
++func secureOpen(containerMount, file string) (*os.File, error) {
++ filePath, err := securejoin.SecureJoin(containerMount, file)
++ if err != nil {
++ return nil, err
++ }
++
++ flags := unix.O_PATH | unix.O_CLOEXEC | unix.O_RDONLY
++ fileHandle, err := os.OpenFile(filePath, flags, 0)
++ if err != nil {
++ return nil, err
++ }
++
++ return fileHandle, nil
++}
+diff --git a/userns_unsupported.go b/userns_unsupported.go
+new file mode 100644
+index 000000000..e37c18fe4
+--- /dev/null
++++ b/userns_unsupported.go
+@@ -0,0 +1,14 @@
++//go:build !linux
++
++package storage
++
++import (
++ "errors"
++
++ "github.com/containers/storage/pkg/idtools"
++ "github.com/containers/storage/types"
++)
++
++func (s *store) getAutoUserNS(_ *types.AutoUserNsOptions, _ *Image, _ rwLayerStore, _ []roLayerStore) ([]idtools.IDMap, []idtools.IDMap, error) {
++ return nil, nil, errors.New("user namespaces are not supported on this platform")
++}
+--
+2.25.1
+
diff --git a/recipes-containers/buildah/buildah_git.bb b/recipes-containers/buildah/buildah_git.bb
index 90ffc238..288a1cb0 100644
--- a/recipes-containers/buildah/buildah_git.bb
+++ b/recipes-containers/buildah/buildah_git.bb
@@ -33,6 +33,7 @@ SRCREV_storage = "246ba3062e8b551026aef2708eee747014ce5c52"
SRC_URI = " \
git://github.com/containers/buildah;branch=release-1.34;name=buildah;protocol=https \
+ file://0001-Use-securejoin.SecureJoin-when-forming-userns-paths.patch;patchdir=src/github.com/containers/buildah/vendor/github.com/containers/storage \
"
DEPENDS = "libdevmapper btrfs-tools gpgme"
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* [meta-virtualization][scarthgap][PATCH 3/3] podman: fix CVE-2024-9676
2025-01-22 2:27 [meta-virtualization][scarthgap][PATCH 1/3] cri-o: update to 1.30.8 Qi.Chen
2025-01-22 2:27 ` [meta-virtualization][scarthgap][PATCH 2/3] buildah: fix CVE-2024-9676 Qi.Chen
@ 2025-01-22 2:27 ` Qi.Chen
2025-01-30 18:53 ` [meta-virtualization][scarthgap][PATCH 1/3] cri-o: update to 1.30.8 Bruce Ashfield
2 siblings, 0 replies; 4+ messages in thread
From: Qi.Chen @ 2025-01-22 2:27 UTC (permalink / raw)
To: meta-virtualization
From: Chen Qi <Qi.Chen@windriver.com>
Backport patch to fix CVE-2024-9676.
Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
---
...SecureJoin-when-forming-userns-paths.patch | 187 ++++++++++++++++++
recipes-containers/podman/podman_git.bb | 1 +
2 files changed, 188 insertions(+)
create mode 100644 recipes-containers/podman/podman/0001-Use-securejoin.SecureJoin-when-forming-userns-paths.patch
diff --git a/recipes-containers/podman/podman/0001-Use-securejoin.SecureJoin-when-forming-userns-paths.patch b/recipes-containers/podman/podman/0001-Use-securejoin.SecureJoin-when-forming-userns-paths.patch
new file mode 100644
index 00000000..585c5638
--- /dev/null
+++ b/recipes-containers/podman/podman/0001-Use-securejoin.SecureJoin-when-forming-userns-paths.patch
@@ -0,0 +1,187 @@
+From 88302fa49db1c1527fee31715e785c44d249976f Mon Sep 17 00:00:00 2001
+From: Matt Heon <mheon@redhat.com>
+Date: Wed, 9 Oct 2024 09:54:22 -0400
+Subject: [PATCH] Use securejoin.SecureJoin when forming userns paths
+
+We need to read /etc/passwd and /etc/group in the container to
+get an idea of how many UIDs and GIDs we need to allocate for a
+user namespace when `--userns=auto` is specified. We were forming
+paths for these using filepath.Join, which is not safe for paths
+within a container, resulting in this CVE allowing crafted
+symlinks in the container to access paths on the host instead.
+
+Cherry-pick conflict fixed for v1.51 branch, and converted to use
+the old securejoin API (securejoin.SecureJoin and then os.Open)
+as this branch is too old to have the new API.
+
+Addresses CVE-2024-9676
+
+Signed-off-by: Matt Heon <mheon@redhat.com>
+
+CVE: CVE-2024-9676
+
+Upstream-Status: Backport [0dc4fc9bb826e08b6e25af0af6a296ac172b5e15]
+
+Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
+---
+ userns.go | 92 ++++++++++++++++++++++++++++++-------------
+ userns_unsupported.go | 14 +++++++
+ 2 files changed, 79 insertions(+), 27 deletions(-)
+ create mode 100644 userns_unsupported.go
+
+diff --git a/userns.go b/userns.go
+index 57120731b..913acf7c5 100644
+--- a/userns.go
++++ b/userns.go
+@@ -1,10 +1,11 @@
++//go:build linux
++
+ package storage
+
+ import (
+ "fmt"
+ "os"
+ "os/user"
+- "path/filepath"
+ "strconv"
+
+ drivers "github.com/containers/storage/drivers"
+@@ -12,7 +13,9 @@ import (
+ "github.com/containers/storage/pkg/unshare"
+ "github.com/containers/storage/types"
+ libcontainerUser "github.com/moby/sys/user"
++ securejoin "github.com/cyphar/filepath-securejoin"
+ "github.com/sirupsen/logrus"
++ "golang.org/x/sys/unix"
+ )
+
+ // getAdditionalSubIDs looks up the additional IDs configured for
+@@ -85,40 +88,59 @@ const nobodyUser = 65534
+ // parseMountedFiles returns the maximum UID and GID found in the /etc/passwd and
+ // /etc/group files.
+ func parseMountedFiles(containerMount, passwdFile, groupFile string) uint32 {
++ var (
++ passwd *os.File
++ group *os.File
++ size int
++ err error
++ )
+ if passwdFile == "" {
+- passwdFile = filepath.Join(containerMount, "etc/passwd")
+- }
+- if groupFile == "" {
+- groupFile = filepath.Join(groupFile, "etc/group")
++ passwd, err = secureOpen(containerMount, "/etc/passwd")
++ } else {
++ // User-specified override from a volume. Will not be in
++ // container root.
++ passwd, err = os.Open(passwdFile)
+ }
+-
+- size := 0
+-
+- users, err := libcontainerUser.ParsePasswdFile(passwdFile)
+ if err == nil {
+- for _, u := range users {
+- // Skip the "nobody" user otherwise we end up with 65536
+- // ids with most images
+- if u.Name == "nobody" {
+- continue
+- }
+- if u.Uid > size && u.Uid != nobodyUser {
+- size = u.Uid
+- }
+- if u.Gid > size && u.Gid != nobodyUser {
+- size = u.Gid
++ defer passwd.Close()
++
++ users, err := libcontainerUser.ParsePasswd(passwd)
++ if err == nil {
++ for _, u := range users {
++ // Skip the "nobody" user otherwise we end up with 65536
++ // ids with most images
++ if u.Name == "nobody" || u.Name == "nogroup" {
++ continue
++ }
++ if u.Uid > size && u.Uid != nobodyUser {
++ size = u.Uid + 1
++ }
++ if u.Gid > size && u.Gid != nobodyUser {
++ size = u.Gid + 1
++ }
+ }
+ }
+ }
+
+- groups, err := libcontainerUser.ParseGroupFile(groupFile)
++ if groupFile == "" {
++ group, err = secureOpen(containerMount, "/etc/group")
++ } else {
++ // User-specified override from a volume. Will not be in
++ // container root.
++ group, err = os.Open(groupFile)
++ }
+ if err == nil {
+- for _, g := range groups {
+- if g.Name == "nobody" {
+- continue
+- }
+- if g.Gid > size && g.Gid != nobodyUser {
+- size = g.Gid
++ defer group.Close()
++
++ groups, err := libcontainerUser.ParseGroup(group)
++ if err == nil {
++ for _, g := range groups {
++ if g.Name == "nobody" || g.Name == "nogroup" {
++ continue
++ }
++ if g.Gid > size && g.Gid != nobodyUser {
++ size = g.Gid + 1
++ }
+ }
+ }
+ }
+@@ -309,3 +331,19 @@ func getAutoUserNSIDMappings(
+ gidMap := append(availableGIDs.zip(requestedContainerGIDs), additionalGIDMappings...)
+ return uidMap, gidMap, nil
+ }
++
++// Securely open (read-only) a file in a container mount.
++func secureOpen(containerMount, file string) (*os.File, error) {
++ filePath, err := securejoin.SecureJoin(containerMount, file)
++ if err != nil {
++ return nil, err
++ }
++
++ flags := unix.O_PATH | unix.O_CLOEXEC | unix.O_RDONLY
++ fileHandle, err := os.OpenFile(filePath, flags, 0)
++ if err != nil {
++ return nil, err
++ }
++
++ return fileHandle, nil
++}
+diff --git a/userns_unsupported.go b/userns_unsupported.go
+new file mode 100644
+index 000000000..e37c18fe4
+--- /dev/null
++++ b/userns_unsupported.go
+@@ -0,0 +1,14 @@
++//go:build !linux
++
++package storage
++
++import (
++ "errors"
++
++ "github.com/containers/storage/pkg/idtools"
++ "github.com/containers/storage/types"
++)
++
++func (s *store) getAutoUserNS(_ *types.AutoUserNsOptions, _ *Image, _ rwLayerStore, _ []roLayerStore) ([]idtools.IDMap, []idtools.IDMap, error) {
++ return nil, nil, errors.New("user namespaces are not supported on this platform")
++}
+--
+2.25.1
+
diff --git a/recipes-containers/podman/podman_git.bb b/recipes-containers/podman/podman_git.bb
index 32de3f0c..8b4f0680 100644
--- a/recipes-containers/podman/podman_git.bb
+++ b/recipes-containers/podman/podman_git.bb
@@ -22,6 +22,7 @@ SRC_URI = " \
git://github.com/containers/libpod.git;branch=v5.0;protocol=https \
${@bb.utils.contains('PACKAGECONFIG', 'rootless', 'file://50-podman-rootless.conf', '', d)} \
file://run-ptest \
+ file://0001-Use-securejoin.SecureJoin-when-forming-userns-paths.patch;patchdir=src/import/vendor/github.com/containers/storage \
"
LICENSE = "Apache-2.0"
--
2.25.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [meta-virtualization][scarthgap][PATCH 1/3] cri-o: update to 1.30.8
2025-01-22 2:27 [meta-virtualization][scarthgap][PATCH 1/3] cri-o: update to 1.30.8 Qi.Chen
2025-01-22 2:27 ` [meta-virtualization][scarthgap][PATCH 2/3] buildah: fix CVE-2024-9676 Qi.Chen
2025-01-22 2:27 ` [meta-virtualization][scarthgap][PATCH 3/3] podman: " Qi.Chen
@ 2025-01-30 18:53 ` Bruce Ashfield
2 siblings, 0 replies; 4+ messages in thread
From: Bruce Ashfield @ 2025-01-30 18:53 UTC (permalink / raw)
To: Qi.Chen; +Cc: meta-virtualization
merged.
Bruce
In message: [meta-virtualization][scarthgap][PATCH 1/3] cri-o: update to 1.30.8
on 21/01/2025 Chen Qi via lists.yoctoproject.org wrote:
> From: Chen Qi <Qi.Chen@windriver.com>
>
> The following two patches are dropped as they are in 1.30.8:
> - CVE-2024-5154-0001.patch
> - CVE-2024-5154-0002.patch
>
> Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
> ---
> recipes-containers/cri-o/cri-o_git.bb | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/recipes-containers/cri-o/cri-o_git.bb b/recipes-containers/cri-o/cri-o_git.bb
> index 4e17a7cd..1d0aa72e 100644
> --- a/recipes-containers/cri-o/cri-o_git.bb
> +++ b/recipes-containers/cri-o/cri-o_git.bb
> @@ -14,7 +14,7 @@ At a high level, we expect the scope of cri-o to be restricted to the following
> - Resource isolation as required by the CRI \
> "
>
> -SRCREV_cri-o = "5aff11c7c1afdc785adafd7da3c3f2a6ac51b88d"
> +SRCREV_cri-o = "359f960f46697517f048e6ff3caf728ae75cb384"
> SRC_URI = "\
> git://github.com/kubernetes-sigs/cri-o.git;branch=release-1.30;name=cri-o;protocol=https \
> file://crio.conf \
> @@ -26,7 +26,7 @@ LIC_FILES_CHKSUM = "file://src/import/LICENSE;md5=e3fc50a88d0a364313df4b21ef20c2
>
> GO_IMPORT = "import"
>
> -PV = "1.30.0+git${SRCREV_cri-o}"
> +PV = "1.30.8+git${SRCREV_cri-o}"
>
> inherit features_check
> REQUIRED_DISTRO_FEATURES ?= "seccomp"
> --
> 2.25.1
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#9103): https://lists.yoctoproject.org/g/meta-virtualization/message/9103
> Mute This Topic: https://lists.yoctoproject.org/mt/110746674/1050810
> Group Owner: meta-virtualization+owner@lists.yoctoproject.org
> Unsubscribe: https://lists.yoctoproject.org/g/meta-virtualization/unsub [bruce.ashfield@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
^ permalink raw reply [flat|nested] 4+ messages in thread