Package: release.debian.org Severity: normal Tags: bullseye X-Debbugs-Cc: r...@packages.debian.org Control: affects -1 + src:runc User: release.debian....@packages.debian.org Usertags: pu
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 [ Reason ] This proposed update fixes all the outstanding CVEs in runc that have already been fixed in Buster, Bookworm, and Trixie/Sid. The affected CVEs are: - - CVE-2021-43784 - - CVE-2023-25809 - - CVE-2023-27561/CVE-2023-28642 This upload also fixes the autopkgtest runs by fixing the location of the busybox tarball and a test that is not compatible with modern kernels. I'm actually wondering why this hasn't been caught by the last upload to b-pu. This upload is in preparation for the upcoming start of Bullseye-LTS and to fix CVEs in Bullseye that have already been fixed in Buster (https://lists.debian.org/debian-lts/2024/04/msg00113.html). [ Impact ] Systems will be vulnerable against the discovered issues in the listed CVEs. [ Tests ] Both, build-time tests and autopkgtests cover the code. For CVE-2023-25809 and CVE-2023-27561/CVE-2023-28642, tests added by upstream are part of the patches. [ Risks ] The worst case would be that regressions or bugs might be introduced. However, no regressions have been detected yet. And all tests have been successful. [ 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 ] * d/patches/0025-Fix-busybox-tarball-url-in-integration-test.patch: Updated. - Fixed download URLs again. * d/patches/CVE-2021-43784.patch: Added to fix CVE-2021-43784. - When writing netlink messages, it is possible to have a byte array larger than UINT16_MAX which would result in the length field overflowing and allowing user-controlled data to be parsed as control characters (such as creating custom mount points, changing which set of namespaces to allow, and so on). * d/patches/0027-Fix-test-for-newer-kernels.patch: Added. - Fix test for newer kernels. * d/patches/CVE-2023-25809.patch: Added to fix CVE-2023-25809. - It was found that rootless runc makes `/sys/fs/cgroup` writable under specific conditions. A container may then gain the write access to user-owned cgroup hierarchy `/sys/fs/cgroup/user.slice/...` on the host. * d/patches/CVE-2023-27561-and-CVE-2023-28642: Added to fix CVE-2023-27561 and CVE-2023-27561. - It was found that the fix for CVE-2021-30465 introduced a regression in regards to CVE-2019-19921 which results in an incorrect access control leading to privilege escalation and bypassing apparmor. [ Other info ] n/a -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEvu1N7VVEpMA+KD3HS80FZ8KW0F0FAmZZBsQACgkQS80FZ8KW 0F0GhRAAp11w2HCzkMQ020IDMcOKs9JrN5BlWc4HXm9CfAFv1WpiiGHbTfUt+mBZ T3QqiGuEIOP7hKdp5YegUXJutKVoDumK5E+CGzA11HqzxpMhEG+Lh+oVQr9sBzMA lwpXRDwZ77gw034xVhDZMLoPKzO5rwA/oy7Am1fHcxtyqEQkFV1bFOShIzog2L4+ U93xM+ixp6rQJsOb0bY9K+h+xP21RczdZu4WqBZ4e447cI0V5CniI72fcp9mjEt9 IRTLyWB0AlbziqSX1nkMevVdoKZSOk5Z9O4izpV/g1v0RLI9Hrbip3RE9Ve6Kl8p a1JtjYm/01uMD8HrMUowuRiHvKkd4Or2Z6QyT5kboWMQg6M15BRfWrjrsD3/DUJJ WGnj78VuoPVWIYrrPD3fOn58xXtMm4HY+CdxFHZDMPgnIXTtEkErGqjiW61O5C6S 73i7HFQB9YCdHHkb4lhkcb1nN3B1Cy35Ez+CzQ3aZ4XjNaq9Yr5s3DvztEyzU1j0 c0K/Ds0k01aKIQm5J7bXeJDHyL3KRv9IgLp25pA+TKv/QgESZ8AEaUu6LaOaETwg Vo93R1zyg0PlMJhriIJX2dtjNjKA5X3WSb/ClZvqtODB6kfBAb27dnjivObK66N8 kFWsaSs5aRzXsL8qlWyDjT7Al6jYY+5yTGqscZStGjS6DMWKa+0= =HO6L -----END PGP SIGNATURE-----
diff -Nru runc-1.0.0~rc93+ds1/debian/changelog runc-1.0.0~rc93+ds1/debian/changelog --- runc-1.0.0~rc93+ds1/debian/changelog 2024-02-02 16:14:13.000000000 +0100 +++ runc-1.0.0~rc93+ds1/debian/changelog 2024-05-31 00:39:22.000000000 +0200 @@ -1,3 +1,28 @@ +runc (1.0.0~rc93+ds1-5+deb11u4) bullseye; urgency=medium + + * Non-maintainer upload by the Debian LTS Team. + * d/patches/0025-Fix-busybox-tarball-url-in-integration-test.patch: Updated. + - Fixed download URLs again. + * d/patches/CVE-2021-43784.patch: Added to fix CVE-2021-43784. + - When writing netlink messages, it is possible to have a byte array larger + than UINT16_MAX which would result in the length field overflowing and + allowing user-controlled data to be parsed as control characters (such as + creating custom mount points, changing which set of namespaces to allow, + and so on). + * d/patches/0027-Fix-test-for-newer-kernels.patch: Added. + - Fix test for newer kernels. + * d/patches/CVE-2023-25809.patch: Added to fix CVE-2023-25809. + - It was found that rootless runc makes `/sys/fs/cgroup` writable under + specific conditions. A container may then gain the write access to + user-owned cgroup hierarchy `/sys/fs/cgroup/user.slice/...` on the host. + * d/patches/CVE-2023-27561-and-CVE-2023-28642: Added to fix CVE-2023-27561 + and CVE-2023-27561. + - It was found that the fix for CVE-2021-30465 introduced a regression in + regards to CVE-2019-19921 which results in an incorrect access control + leading to privilege escalation and bypassing apparmor. + + -- Daniel Leidert <dleid...@debian.org> Fri, 31 May 2024 00:39:22 +0200 + runc (1.0.0~rc93+ds1-5+deb11u3) bullseye-security; urgency=high * Team upload. diff -Nru runc-1.0.0~rc93+ds1/debian/.gitlab-ci.yml runc-1.0.0~rc93+ds1/debian/.gitlab-ci.yml --- runc-1.0.0~rc93+ds1/debian/.gitlab-ci.yml 2024-02-02 16:14:13.000000000 +0100 +++ runc-1.0.0~rc93+ds1/debian/.gitlab-ci.yml 2024-05-31 00:39:22.000000000 +0200 @@ -1,37 +1,10 @@ --- -# https://docs.gitlab.com/ce/ci/yaml/#include include: - - remote: https://salsa.debian.org/onlyjob/ci/raw/master/onlyjob-ci.yml + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml + - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml -## "amd64-unstable" always runs by default followed by lintian. - -## Only for arch:all packages - remove if not required: -binary-indep: - extends: .build-indep - -## Job to check Build-Depends versioning: -amd64-testing_unstable: - extends: .build - variables: - arch: amd64 - dist: testing_unstable - -i386-unstable: - extends: .build - variables: - arch: i386 - dist: unstable - -amd64-experimental: - extends: .build - variables: - arch: amd64 - dist: experimental - -amd64-stable: - extends: .build - when: manual - allow_failure: true - variables: - arch: amd64 - dist: stable +variables: + RELEASE: 'bullseye' + SALSA_CI_COMPONENTS: 'main contrib non-free' + SALSA_CI_DISABLE_REPROTEST: 1 + SALSA_CI_DISABLE_LINTIAN: 1 diff -Nru runc-1.0.0~rc93+ds1/debian/patches/0025-Fix-busybox-tarball-url-in-integration-test.patch runc-1.0.0~rc93+ds1/debian/patches/0025-Fix-busybox-tarball-url-in-integration-test.patch --- runc-1.0.0~rc93+ds1/debian/patches/0025-Fix-busybox-tarball-url-in-integration-test.patch 2024-02-02 16:14:13.000000000 +0100 +++ runc-1.0.0~rc93+ds1/debian/patches/0025-Fix-busybox-tarball-url-in-integration-test.patch 2024-05-31 00:39:22.000000000 +0200 @@ -2,12 +2,15 @@ Date: Sat, 3 Feb 2024 00:02:52 +0800 Subject: Fix busybox tarball url in integration test +https://github.com/opencontainers/runc/blob/main/tests/integration/get-images.sh + +Reviewed-by: Daniel Leidert <dleid...@debian.org> --- tests/integration/multi-arch.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/multi-arch.bash b/tests/integration/multi-arch.bash -index 1dd751b..91d2c1d 100644 +index 1dd751b..0e07a11 100644 --- a/tests/integration/multi-arch.bash +++ b/tests/integration/multi-arch.bash @@ -2,10 +2,10 @@ @@ -15,11 +18,11 @@ case $(go env GOARCH) in arm64) - echo 'https://github.com/docker-library/busybox/raw/dist-arm64v8/stable/glibc/busybox.tar.xz' -+ echo 'https://github.com/docker-library/busybox/raw/dist-arm64v8/latest/glibc/busybox.tar.xz' ++ echo 'https://github.com/docker-library/busybox/raw/94c664b5ca464546266bce54be0082874a44c7b2/stable/glibc/busybox.tar.xz' ;; *) - echo 'https://github.com/docker-library/busybox/raw/dist-amd64/stable/glibc/busybox.tar.xz' -+ echo 'https://github.com/docker-library/busybox/raw/dist-amd64/latest/glibc/busybox.tar.xz' ++ echo 'https://github.com/docker-library/busybox/raw/31d342ad033e27c18723a516a2274ab39547be27/stable/glibc/busybox.tar.xz' ;; esac } diff -Nru runc-1.0.0~rc93+ds1/debian/patches/0027-Fix-test-for-newer-kernels.patch runc-1.0.0~rc93+ds1/debian/patches/0027-Fix-test-for-newer-kernels.patch --- runc-1.0.0~rc93+ds1/debian/patches/0027-Fix-test-for-newer-kernels.patch 1970-01-01 01:00:00.000000000 +0100 +++ runc-1.0.0~rc93+ds1/debian/patches/0027-Fix-test-for-newer-kernels.patch 2024-05-31 00:39:22.000000000 +0200 @@ -0,0 +1,43 @@ +From: Kir Kolyshkin <kolysh...@gmail.com> +Date: Tue, 29 Jun 2021 13:19:42 -0700 +Subject: [PATCH] tests/int/no_pivot: fix for new kernels + +The test is failing like this: + + not ok 70 runc run --no-pivot must not expose bare /proc + # (in test file tests/integration/no_pivot.bats, line 20) + # `[[ "$output" == *"mount: permission denied"* ]]' failed + # runc spec (status=0): + # + # runc run --no-pivot test_no_pivot (status=1): + # unshare: write error: Operation not permitted + +Apparently, a recent kernel commit db2e718a47984b9d prevents +root from doing unshare -r unless it has CAP_SETFPCAP. + +Add the capability for this specific test. + +Signed-off-by: Kir Kolyshkin <kolysh...@gmail.com> + +Acked-by: Daniel Leidert <dleid...@debian.org> +Origin: https://github.com/opencontainers/runc/commit/1bbeadae72603c44932d46ade275219dbf718950.patch +Forwarded: not-needed +--- + tests/integration/no_pivot.bats | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tests/integration/no_pivot.bats b/tests/integration/no_pivot.bats +index 844a0ca..da6e386 100644 +--- a/tests/integration/no_pivot.bats ++++ b/tests/integration/no_pivot.bats +@@ -14,7 +14,9 @@ function teardown() { + @test "runc run --no-pivot must not expose bare /proc" { + requires root + +- update_config '.process.args |= ["unshare", "-mrpf", "sh", "-euxc", "mount -t proc none /proc && echo h > /proc/sysrq-trigger"]' ++ update_config ' .process.args |= ["unshare", "-mrpf", "sh", "-euxc", "mount -t proc none /proc && echo h > /proc/sysrq-trigger"] ++ | .process.capabilities.bounding += ["CAP_SETFCAP"] ++ | .process.capabilities.permitted += ["CAP_SETFCAP"]' + + runc run --no-pivot test_no_pivot + [ "$status" -eq 1 ] diff -Nru runc-1.0.0~rc93+ds1/debian/patches/CVE-2021-43784.patch runc-1.0.0~rc93+ds1/debian/patches/CVE-2021-43784.patch --- runc-1.0.0~rc93+ds1/debian/patches/CVE-2021-43784.patch 1970-01-01 01:00:00.000000000 +0100 +++ runc-1.0.0~rc93+ds1/debian/patches/CVE-2021-43784.patch 2024-05-31 00:39:22.000000000 +0200 @@ -0,0 +1,87 @@ +From: Kir Kolyshkin <kolysh...@gmail.com> +Date: Sun, 18 Feb 2024 22:46:19 +0100 +Subject: Fix CVE-2021-43784 + +When writing netlink messages, it is possible to have a byte array +larger than UINT16_MAX which would result in the length field +overflowing and allowing user-controlled data to be parsed as control +characters (such as creating custom mount points, changing which set of +namespaces to allow, and so on). + +Reviewed-by: Daniel Leidert <dleid...@debian.org> +Origin: https://github.com/opencontainers/runc/commit/d72d057ba794164c3cce9451a00b72a78b25e1ae +Bug: https://github.com/opencontainers/runc/security/advisories/GHSA-v95c-p5hm-xq8f +Forwarded: not-needed +--- + libcontainer/container_linux.go | 20 +++++++++++++++++++- + libcontainer/message_linux.go | 10 ++++++++++ + 2 files changed, 29 insertions(+), 1 deletion(-) + +diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go +index c95b83e..6c2cfd3 100644 +--- a/libcontainer/container_linux.go ++++ b/libcontainer/container_linux.go +@@ -1982,16 +1982,34 @@ func encodeIDMapping(idMap []configs.IDMap) ([]byte, error) { + return data.Bytes(), nil + } + ++// netlinkError is an error wrapper type for use by custom netlink message ++// types. Panics with errors are wrapped in netlinkError so that the recover ++// in bootstrapData can distinguish intentional panics. ++type netlinkError struct{ error } ++ + // bootstrapData encodes the necessary data in netlink binary format + // as a io.Reader. + // Consumer can write the data to a bootstrap program + // such as one that uses nsenter package to bootstrap the container's + // init process correctly, i.e. with correct namespaces, uid/gid + // mapping etc. +-func (c *linuxContainer) bootstrapData(cloneFlags uintptr, nsMaps map[configs.NamespaceType]string) (io.Reader, error) { ++func (c *linuxContainer) bootstrapData(cloneFlags uintptr, nsMaps map[configs.NamespaceType]string) (_ io.Reader, Err error) { + // create the netlink message + r := nl.NewNetlinkRequest(int(InitMsg), 0) + ++ // Our custom messages cannot bubble up an error using returns, instead ++ // they will panic with the specific error type, netlinkError. In that ++ // case, recover from the panic and return that as an error. ++ defer func() { ++ if r := recover(); r != nil { ++ if e, ok := r.(netlinkError); ok { ++ Err = e.error ++ } else { ++ panic(r) ++ } ++ } ++ }() ++ + // write cloneFlags + r.AddData(&Int32msg{ + Type: CloneFlagsAttr, +diff --git a/libcontainer/message_linux.go b/libcontainer/message_linux.go +index 1d4f503..4726f37 100644 +--- a/libcontainer/message_linux.go ++++ b/libcontainer/message_linux.go +@@ -3,6 +3,9 @@ + package libcontainer + + import ( ++ "fmt" ++ "math" ++ + "github.com/vishvananda/netlink/nl" + "golang.org/x/sys/unix" + ) +@@ -32,6 +35,13 @@ type Int32msg struct { + // | nlattr len | nlattr type | + // | uint32 value | + func (msg *Int32msg) Serialize() []byte { ++ l := msg.Len() ++ if l > math.MaxUint16 { ++ // We cannot return nil nor an error here, so we panic with ++ // a specific type instead, which is handled via recover in ++ // bootstrapData. ++ panic(netlinkError{fmt.Errorf("netlink: cannot serialize bytemsg of length %d (larger than UINT16_MAX)", l)}) ++ } + buf := make([]byte, msg.Len()) + native := nl.NativeEndian() + native.PutUint16(buf[0:2], uint16(msg.Len())) diff -Nru runc-1.0.0~rc93+ds1/debian/patches/CVE-2023-25809.patch runc-1.0.0~rc93+ds1/debian/patches/CVE-2023-25809.patch --- runc-1.0.0~rc93+ds1/debian/patches/CVE-2023-25809.patch 1970-01-01 01:00:00.000000000 +0100 +++ runc-1.0.0~rc93+ds1/debian/patches/CVE-2023-25809.patch 2024-05-31 00:39:22.000000000 +0200 @@ -0,0 +1,124 @@ +From: Akihiro Suda <akihiro.suda...@hco.ntt.co.jp> +Date: Mon, 26 Dec 2022 12:04:26 +0900 +Subject: [PATCH] rootless: fix /sys/fs/cgroup mounts + +It was found that rootless runc makes `/sys/fs/cgroup` writable in following conditons: + +1. when runc is executed inside the user namespace, and the config.json does not specify the cgroup namespace to be unshared + (e.g.., `(docker|podman|nerdctl) run --cgroupns=host`, with Rootless Docker/Podman/nerdctl) +2. or, when runc is executed outside the user namespace, and `/sys` is mounted with `rbind, ro` + (e.g., `runc spec --rootless`; this condition is very rare) + +A container may gain the write access to user-owned cgroup hierarchy `/sys/fs/cgroup/user.slice/...` on the host. +Other users's cgroup hierarchies are not affected. + +To fix the issue, this commit does: +1. Remount `/sys/fs/cgroup` to apply `MS_RDONLY` when it is being bind-mounted +2. Mask `/sys/fs/cgroup` when the bind source is unavailable + +Fix CVE-2023-25809 (GHSA-m8cg-xc2p-r3fc) + +Co-authored-by: Kir Kolyshkin <kolysh...@gmail.com> +Signed-off-by: Akihiro Suda <akihiro.suda...@hco.ntt.co.jp> +(cherry picked from commit df4eae457b8ccffa619c659c2def5c777d8ff507) +Signed-off-by: Akihiro Suda <akihiro.suda...@hco.ntt.co.jp> + +Acked-by: Daniel Leidert <dleid...@debian.org> +Origin: https://github.com/opencontainers/runc/commit/0e6b818a2b0d24fdb6697614e5c5f115bbe8e3a5.patch +Bug: https://github.com/opencontainers/runc/security/advisories/GHSA-m8cg-xc2p-r3fc +Forwarded: not-needed +--- + libcontainer/rootfs_linux.go | 53 +++++++++++++++++++++++++++---------------- + tests/integration/mounts.bats | 17 ++++++++++++++ + 2 files changed, 51 insertions(+), 19 deletions(-) + +diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go +index 96be669..4791ceb 100644 +--- a/libcontainer/rootfs_linux.go ++++ b/libcontainer/rootfs_linux.go +@@ -309,26 +309,41 @@ func mountCgroupV2(m *configs.Mount, c *mountConfig) error { + if err := os.MkdirAll(dest, 0755); err != nil { + return err + } +- return utils.WithProcfd(c.root, m.Destination, func(procfd string) error { +- if err := unix.Mount(m.Source, procfd, "cgroup2", uintptr(m.Flags), m.Data); err != nil { +- // when we are in UserNS but CgroupNS is not unshared, we cannot mount cgroup2 (#2158) +- if err == unix.EPERM || err == unix.EBUSY { +- src := fs2.UnifiedMountpoint +- if c.cgroupns && c.cgroup2Path != "" { +- // Emulate cgroupns by bind-mounting +- // the container cgroup path rather than +- // the whole /sys/fs/cgroup. +- src = c.cgroup2Path +- } +- err = unix.Mount(src, procfd, "", uintptr(m.Flags)|unix.MS_BIND, "") +- if err == unix.ENOENT && c.rootlessCgroups { +- err = nil +- } +- } +- return err +- } +- return nil ++ err = utils.WithProcfd(c.root, m.Destination, func(procfd string) error { ++ return unix.Mount(m.Source, procfd, "cgroup2", uintptr(m.Flags), m.Data) + }) ++ if err == nil || !(err == unix.EPERM || err == unix.EBUSY) { ++ return err ++ } ++ ++ // When we are in UserNS but CgroupNS is not unshared, we cannot mount ++ // cgroup2 (#2158), so fall back to bind mount. ++ bindM := &configs.Mount{ ++ Device: "bind", ++ Source: fs2.UnifiedMountpoint, ++ Destination: m.Destination, ++ Flags: unix.MS_BIND | m.Flags, ++ PropagationFlags: m.PropagationFlags, ++ } ++ if c.cgroupns && c.cgroup2Path != "" { ++ // Emulate cgroupns by bind-mounting the container cgroup path ++ // rather than the whole /sys/fs/cgroup. ++ bindM.Source = c.cgroup2Path ++ } ++ // mountToRootfs() handles remounting for MS_RDONLY. ++ // No need to set c.fd here, because mountToRootfs() calls utils.WithProcfd() by itself in mountPropagate(). ++ err = mountToRootfs(bindM, c) ++ if c.rootlessCgroups && err == unix.ENOENT { ++ // ENOENT (for `src = c.cgroup2Path`) happens when rootless runc is being executed ++ // outside the userns+mountns. ++ // ++ // Mask `/sys/fs/cgroup` to ensure it is read-only, even when `/sys` is mounted ++ // with `rbind,ro` (`runc spec --rootless` produces `rbind,ro` for `/sys`). ++ err = utils.WithProcfd(c.root, m.Destination, func(procfd string) error { ++ return maskPath(procfd, c.label) ++ }) ++ } ++ return err + } + + func doTmpfsCopyUp(m *configs.Mount, rootfs, mountLabel string) (Err error) { +diff --git a/tests/integration/mounts.bats b/tests/integration/mounts.bats +index a4b9f29..ae39a72 100644 +--- a/tests/integration/mounts.bats ++++ b/tests/integration/mounts.bats +@@ -53,3 +53,20 @@ function teardown() { + runc run test_busybox + [ "$status" -eq 0 ] + } ++ ++# https://github.com/opencontainers/runc/security/advisories/GHSA-m8cg-xc2p-r3fc ++@test "runc run [ro /sys/fs/cgroup mount]" { ++ # With cgroup namespace ++ update_config '.process.args |= ["sh", "-euc", "for f in `grep /sys/fs/cgroup /proc/mounts | awk \"{print \\\\$2}\"| uniq`; do grep -w $f /proc/mounts | tail -n1; done"]' ++ runc run test_busybox ++ [ "$status" -eq 0 ] ++ [ "${#lines[@]}" -ne 0 ] ++ for line in "${lines[@]}"; do [[ "${line}" == *'ro,'* ]]; done ++ ++ # Without cgroup namespace ++ update_config '.linux.namespaces -= [{"type": "cgroup"}]' ++ runc run test_busybox ++ [ "$status" -eq 0 ] ++ [ "${#lines[@]}" -ne 0 ] ++ for line in "${lines[@]}"; do [[ "${line}" == *'ro,'* ]]; done ++} diff -Nru runc-1.0.0~rc93+ds1/debian/patches/CVE-2023-27561-and-CVE-2023-28642.patch runc-1.0.0~rc93+ds1/debian/patches/CVE-2023-27561-and-CVE-2023-28642.patch --- runc-1.0.0~rc93+ds1/debian/patches/CVE-2023-27561-and-CVE-2023-28642.patch 1970-01-01 01:00:00.000000000 +0100 +++ runc-1.0.0~rc93+ds1/debian/patches/CVE-2023-27561-and-CVE-2023-28642.patch 2024-05-31 00:39:22.000000000 +0200 @@ -0,0 +1,109 @@ +From: Kir Kolyshkin <kolysh...@gmail.com> +Date: Thu, 16 Mar 2023 14:35:50 -0700 +Subject: [PATCH] Prohibit /proc and /sys to be symlinks + +Commit 3291d66b9844 introduced a check for /proc and /sys, making sure +the destination (dest) is a directory (and not e.g. a symlink). + +Later, a hunk from commit 0ca91f44f switched from using filepath.Join +to SecureJoin for dest. As SecureJoin follows and resolves symlinks, +the check whether dest is a symlink no longer works. + +To fix, do the check without/before using SecureJoin. + +Add integration tests to make sure we won't regress. + +Signed-off-by: Kir Kolyshkin <kolysh...@gmail.com> +(cherry picked from commit 0d72adf96dda1b687815bf89bb245b937a2f603c) +Signed-off-by: Sebastiaan van Stijn <git...@gone.nl> + +This patch fixes both, CVE-2023-27561 and CVE-2023-28642 + +Acked-by: Daniel Leidert <dleid...@debian.org> +Origin: https://github.com/opencontainers/runc/commit/0abab45c9b97c113ff2cdc16f3a7388444c3fbec.patch +Forwarded: not-needed +--- + libcontainer/rootfs_linux.go | 23 +++++++++++++++++------ + tests/integration/mask.bats | 19 +++++++++++++++++++ + 2 files changed, 36 insertions(+), 6 deletions(-) + +diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go +index 4791ceb..07303b0 100644 +--- a/libcontainer/rootfs_linux.go ++++ b/libcontainer/rootfs_linux.go +@@ -393,12 +393,9 @@ func doTmpfsCopyUp(m *configs.Mount, rootfs, mountLabel string) (Err error) { + + func mountToRootfs(m *configs.Mount, c *mountConfig) error { + rootfs := c.root +- mountLabel := c.label +- dest, err := securejoin.SecureJoin(rootfs, m.Destination) +- if err != nil { +- return err +- } + ++ // procfs and sysfs are special because we need to ensure they are actually ++ // mounted on a specific path in a container without any funny business. + switch m.Device { + case "proc", "sysfs": + // If the destination already exists and is not a directory, we bail +@@ -406,11 +403,16 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error { + // has been a "fun" attack scenario in the past. + // TODO: This won't be necessary once we switch to libpathrs and we can + // stop all of these symlink-exchange attacks. ++ dest := filepath.Clean(m.Destination) ++ if !strings.HasPrefix(dest, rootfs) { ++ // Do not use securejoin as it resolves symlinks. ++ dest = filepath.Join(rootfs, dest) ++ } + if fi, err := os.Lstat(dest); err != nil { + if !os.IsNotExist(err) { + return err + } +- } else if fi.Mode()&os.ModeDir == 0 { ++ } else if !fi.IsDir() { + return fmt.Errorf("filesystem %q must be mounted on ordinary directory", m.Device) + } + if err := os.MkdirAll(dest, 0755); err != nil { +@@ -418,6 +420,15 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error { + } + // Selinux kernels do not support labeling of /proc or /sys + return mountPropagate(m, rootfs, "") ++ } ++ ++ mountLabel := c.label ++ dest, err := securejoin.SecureJoin(rootfs, m.Destination) ++ if err != nil { ++ return err ++ } ++ ++ switch m.Device { + case "mqueue": + if err := os.MkdirAll(dest, 0755); err != nil { + return err +diff --git a/tests/integration/mask.bats b/tests/integration/mask.bats +index 0786c2a..107b924 100644 +--- a/tests/integration/mask.bats ++++ b/tests/integration/mask.bats +@@ -57,3 +57,22 @@ function teardown() { + [ "$status" -eq 1 ] + [[ "${output}" == *"Operation not permitted"* ]] + } ++ ++@test "mask paths [prohibit symlink /proc]" { ++ ln -s /symlink rootfs/proc ++ runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox ++ [ "$status" -eq 1 ] ++ [[ "${output}" == *"must be mounted on ordinary directory"* ]] ++} ++ ++@test "mask paths [prohibit symlink /sys]" { ++ # In rootless containers, /sys is a bind mount not a real sysfs. ++ requires root ++ ++ ln -s /symlink rootfs/sys ++ runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox ++ [ "$status" -eq 1 ] ++ # On cgroup v1, this may fail before checking if /sys is a symlink, ++ # so we merely check that it fails, and do not check the exact error ++ # message like for /proc above. ++} diff -Nru runc-1.0.0~rc93+ds1/debian/patches/series runc-1.0.0~rc93+ds1/debian/patches/series --- runc-1.0.0~rc93+ds1/debian/patches/series 2024-02-02 16:14:13.000000000 +0100 +++ runc-1.0.0~rc93+ds1/debian/patches/series 2024-05-31 00:39:22.000000000 +0200 @@ -23,3 +23,7 @@ CVE-2024-21626/0023-libcontainer-mark-all-non-stdio-fds-O_CLOEXEC-before.patch CVE-2024-21626/0024-init-don-t-special-case-logrus-fds.patch 0025-Fix-busybox-tarball-url-in-integration-test.patch +CVE-2021-43784.patch +0027-Fix-test-for-newer-kernels.patch +CVE-2023-25809.patch +CVE-2023-27561-and-CVE-2023-28642.patch