diff -Nru runc-1.1.4/debian/changelog runc-1.1.4/debian/changelog --- runc-1.1.4/debian/changelog 2022-11-17 17:05:31.000000000 +0000 +++ runc-1.1.4/debian/changelog 2023-05-16 10:07:05.000000000 +0000 @@ -1,3 +1,20 @@ +runc (1.1.4-0ubuntu1~18.04.2) bionic-security; urgency=medium + + * d/p/lp2013318-fix-device-files-in-containers.patch: Fix inability to use + device files such as /dev/null in containers (LP: #2013318) + * SECURITY UPDATE: Incorrect access control through /sys/fs/cgroup + - debian/patches/CVE-2023-25809.patch: apply MS_RDONLY if + /sys/fs/cgroup is bind-mounted or mask if bind source is unavailable + in libcontainer/rootfs_linux.go. + - CVE-2023-25809 + * SECURITY UPDATE: Incorrect access control through /proc and /sys + - debian/patches/CVE-2023-27561_2023-28642.patch: Prohibit /proc and + /sys to be symlinks in libcontainer/rootfs_linux.go. + - CVE-2023-27561 + - CVE-2023-28642 + + -- David Fernandez Gonzalez Tue, 16 May 2023 12:07:05 +0200 + runc (1.1.4-0ubuntu1~18.04.1) bionic; urgency=medium * Backport version 1.1.4-0ubuntu1 from Lunar (LP: #1996909). diff -Nru runc-1.1.4/debian/patches/CVE-2023-25809.patch runc-1.1.4/debian/patches/CVE-2023-25809.patch --- runc-1.1.4/debian/patches/CVE-2023-25809.patch 1970-01-01 00:00:00.000000000 +0000 +++ runc-1.1.4/debian/patches/CVE-2023-25809.patch 2023-05-16 08:47:40.000000000 +0000 @@ -0,0 +1,95 @@ +From 0e6b818a2b0d24fdb6697614e5c5f115bbe8e3a5 Mon Sep 17 00:00:00 2001 +From: Akihiro Suda +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 +Signed-off-by: Akihiro Suda +(cherry picked from commit df4eae457b8ccffa619c659c2def5c777d8ff507) +Signed-off-by: Akihiro Suda +--- + 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 ec7638e4d5..99df291524 100644 +--- a/libcontainer/rootfs_linux.go ++++ b/libcontainer/rootfs_linux.go +@@ -329,26 +329,41 @@ func mountCgroupV2(m *configs.Mount, c *mountConfig) error { + if err := os.MkdirAll(dest, 0o755); err != nil { + return err + } +- return utils.WithProcfd(c.root, m.Destination, func(procfd string) error { +- if err := mount(m.Source, m.Destination, 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 errors.Is(err, unix.EPERM) || errors.Is(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 = mount(src, m.Destination, procfd, "", uintptr(m.Flags)|unix.MS_BIND, "") +- if c.rootlessCgroups && errors.Is(err, unix.ENOENT) { +- err = nil +- } +- } +- return err +- } +- return nil ++ err = utils.WithProcfd(c.root, m.Destination, func(procfd string) error { ++ return mount(m.Source, m.Destination, procfd, "cgroup2", uintptr(m.Flags), m.Data) + }) ++ if err == nil || !(errors.Is(err, unix.EPERM) || errors.Is(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 && errors.Is(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 -Nru runc-1.1.4/debian/patches/CVE-2023-27561_2023-28642.patch runc-1.1.4/debian/patches/CVE-2023-27561_2023-28642.patch --- runc-1.1.4/debian/patches/CVE-2023-27561_2023-28642.patch 1970-01-01 00:00:00.000000000 +0000 +++ runc-1.1.4/debian/patches/CVE-2023-27561_2023-28642.patch 2023-05-16 08:47:46.000000000 +0000 @@ -0,0 +1,79 @@ +From 0abab45c9b97c113ff2cdc16f3a7388444c3fbec Mon Sep 17 00:00:00 2001 +From: Kir Kolyshkin +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 +(cherry picked from commit 0d72adf96dda1b687815bf89bb245b937a2f603c) +Signed-off-by: Sebastiaan van Stijn +--- + libcontainer/rootfs_linux.go | 29 ++++++++++++++++++++--------- + tests/integration/mask.bats | 19 +++++++++++++++++++ + 2 files changed, 39 insertions(+), 9 deletions(-) + +--- runc-1.1.4.orig/libcontainer/rootfs_linux.go ++++ runc-1.1.4/libcontainer/rootfs_linux.go +@@ -413,32 +413,43 @@ func doTmpfsCopyUp(m *configs.Mount, roo + + func mountToRootfs(m *configs.Mount, c *mountConfig) error { + rootfs := c.root +- mountLabel := c.label +- mountFd := c.fd +- 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 +- // out This is to avoid mounting through a symlink or similar -- which ++ // out. This is to avoid mounting through a symlink or similar -- which + // 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, 0o755); err != nil { + return err + } +- // Selinux kernels do not support labeling of /proc or /sys ++ // Selinux kernels do not support labeling of /proc or /sys. + return mountPropagate(m, rootfs, "", nil) ++ } ++ ++ mountLabel := c.label ++ mountFd := c.fd ++ dest, err := securejoin.SecureJoin(rootfs, m.Destination) ++ if err != nil { ++ return err ++ } ++ ++ switch m.Device { + case "mqueue": + if err := os.MkdirAll(dest, 0o755); err != nil { + return err diff -Nru runc-1.1.4/debian/patches/lp2013318-fix-device-files-in-containers.patch runc-1.1.4/debian/patches/lp2013318-fix-device-files-in-containers.patch --- runc-1.1.4/debian/patches/lp2013318-fix-device-files-in-containers.patch 1970-01-01 00:00:00.000000000 +0000 +++ runc-1.1.4/debian/patches/lp2013318-fix-device-files-in-containers.patch 2023-05-16 10:06:51.000000000 +0000 @@ -0,0 +1,30 @@ +Description: Fix inability to use /dev/null when inside a container +Author: Evan Phoenix +Origin: upstream, https://github.com/opencontainers/runc/commit/462e719cae227a990ed793241062a8d2d6145332 +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/runc/+bug/2013318 +Last-Update: 2023-04-06 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +--- a/libcontainer/cgroups/systemd/common.go ++++ b/libcontainer/cgroups/systemd/common.go +@@ -293,8 +293,18 @@ + // rules separately to systemd) we can safely skip entries that don't + // have a corresponding path. + if _, err := os.Stat(entry.Path); err != nil { +- logrus.Debugf("skipping device %s for systemd: %s", entry.Path, err) +- continue ++ // Also check /sys/dev so that we don't depend on /dev/{block,char} ++ // being populated. (/dev/{block,char} is populated by udev, which ++ // isn't strictly required for systemd). Ironically, this happens most ++ // easily when starting containerd within a runc created container ++ // itself. ++ ++ // We don't bother with securejoin here because we create entry.Path ++ // right above here, so we know it's safe. ++ if _, err := os.Stat("/sys" + entry.Path); err != nil { ++ logrus.Warnf("skipping device %s for systemd: %s", entry.Path, err) ++ continue ++ } + } + } + deviceAllowList = append(deviceAllowList, entry) diff -Nru runc-1.1.4/debian/patches/series runc-1.1.4/debian/patches/series --- runc-1.1.4/debian/patches/series 2022-11-17 15:31:08.000000000 +0000 +++ runc-1.1.4/debian/patches/series 2023-05-16 10:06:51.000000000 +0000 @@ -1,3 +1,6 @@ test--skip_TestFactoryNewTmpfs.patch test--skip-fs-related-cgroups-tests.patch fix_cpuset_range_byte_order.patch +lp2013318-fix-device-files-in-containers.patch +CVE-2023-25809.patch +CVE-2023-27561_2023-28642.patch