Skip to content
This repository has been archived by the owner on May 30, 2023. It is now read-only.

Commit

Permalink
app-emulation/docker-runc: Backport embargoed CVE-2021-30465 for rc92
Browse files Browse the repository at this point in the history
The upstream patch (itself backported for rc93) was backported to rc92.
Original cover letter:
	From 14faf1c20948688a48edb9b41367ab07ac11ca91 Mon Sep 17 00:00:00 2001
	From: Aleksa Sarai <cyphar@cyphar.com>
	Date: Wed, 28 Apr 2021 15:44:36 +1000
	Subject: [PATCH 0/5] rootfs: add mount destination validation

	This is a backport of the fix for CVE-2021-30465 to the v1.0.0-rc93
	release. However, because the patch does not apply cleanly it was
	necessary to backport the following commits (from [1]):

	 * deb8a8dd7767 ("libct/newInitConfig: nit")
	 * 1e476578b6cd ("libct/rootfs: introduce and use mountConfig")
	 * 3826db196d59 ("libct/rootfs/mountCgroupV2: minor refactor")
	 * ff692f289b60 ("Fix cgroup2 mount for rootless case")

	And the patch itself was modified to remove hardenings for code which
	didn't exist in v1.0.0-rc93 (in particular, the mount changes in [2]).

	[1]: opencontainers/runc#2818
	[2]: opencontainers/runc#2798

	Aleksa Sarai (1):
	  rootfs: add mount destination validation

	Kir Kolyshkin (4):
	  libct/newInitConfig: nit
	  libct/rootfs: introduce and use mountConfig
	  libct/rootfs/mountCgroupV2: minor refactor
	  Fix cgroup2 mount for rootless case

	 libcontainer/container_linux.go  |  11 +-
	 libcontainer/init_linux.go       |   1 +
	 libcontainer/rootfs_linux.go     | 291 +++++++++++++++++--------------
	 libcontainer/specconv/example.go |  18 +-
	 libcontainer/utils/utils.go      |  54 ++++++
	 libcontainer/utils/utils_test.go |  35 ++++
	 6 files changed, 263 insertions(+), 147 deletions(-)

	--
	2.31.1
  • Loading branch information
pothos committed May 19, 2021
1 parent ed3f06c commit 6e0acb8
Show file tree
Hide file tree
Showing 6 changed files with 985 additions and 0 deletions.
5 changes: 5 additions & 0 deletions app-emulation/docker-runc/docker-runc-1.0.0_rc92.ebuild
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ src_unpack() {
PATCHES=(
"${FILESDIR}/0001-Delay-unshare-of-clone-newipc-for-selinux.patch"
"${FILESDIR}/0001-temporarily-disable-selinux.GetEnabled-error-checks.patch"
"${FILESDIR}/rc92-0001-libct-newInitConfig-nit.patch"
"${FILESDIR}/rc92-0002-libct-rootfs-introduce-and-use-mountConfig.patch"
"${FILESDIR}/rc92-0003-libct-rootfs-mountCgroupV2-minor-refactor.patch"
"${FILESDIR}/rc92-0004-Fix-cgroup2-mount-for-rootless-case.patch"
"${FILESDIR}/rc92-0005-rootfs-add-mount-destination-validation.patch"
)

src_compile() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
From 7b2b5e4ca66c5c020848f2fd0d3335a2bb8bec95 Mon Sep 17 00:00:00 2001
Message-Id: <7b2b5e4ca66c5c020848f2fd0d3335a2bb8bec95.1620832610.git.dongsu@kinvolk.io>
From: Kir Kolyshkin <kolyshkin@gmail.com>
Date: Tue, 23 Feb 2021 17:58:07 -0800
Subject: [PATCH 1/5] libct/newInitConfig: nit

Move the initialization of Console* fields as they are unconditional.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
---
libcontainer/container_linux.go | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go
index e2f64fcb..65d64867 100644
--- a/libcontainer/container_linux.go
+++ b/libcontainer/container_linux.go
@@ -607,6 +607,9 @@ func (c *linuxContainer) newInitConfig(process *Process) *initConfig {
AppArmorProfile: c.config.AppArmorProfile,
ProcessLabel: c.config.ProcessLabel,
Rlimits: c.config.Rlimits,
+ CreateConsole: process.ConsoleSocket != nil,
+ ConsoleWidth: process.ConsoleWidth,
+ ConsoleHeight: process.ConsoleHeight,
}
if process.NoNewPrivileges != nil {
cfg.NoNewPrivileges = *process.NoNewPrivileges
@@ -620,9 +623,7 @@ func (c *linuxContainer) newInitConfig(process *Process) *initConfig {
if len(process.Rlimits) > 0 {
cfg.Rlimits = process.Rlimits
}
- cfg.CreateConsole = process.ConsoleSocket != nil
- cfg.ConsoleWidth = process.ConsoleWidth
- cfg.ConsoleHeight = process.ConsoleHeight
+
return cfg
}

--
2.31.1

Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
From 1221cad2a9ab408a0fb73cdb87a4590a460f0fb3 Mon Sep 17 00:00:00 2001
Message-Id: <1221cad2a9ab408a0fb73cdb87a4590a460f0fb3.1620832610.git.dongsu@kinvolk.io>
In-Reply-To: <7b2b5e4ca66c5c020848f2fd0d3335a2bb8bec95.1620832610.git.dongsu@kinvolk.io>
References: <7b2b5e4ca66c5c020848f2fd0d3335a2bb8bec95.1620832610.git.dongsu@kinvolk.io>
From: Kir Kolyshkin <kolyshkin@gmail.com>
Date: Tue, 23 Feb 2021 18:14:37 -0800
Subject: [PATCH 2/5] libct/rootfs: introduce and use mountConfig

The code is already passing three parameters around from
mountToRootfs to mountCgroupV* to mountToRootfs again.

I am about to add another parameter, so let's introduce and
use struct mountConfig to pass around.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
---
libcontainer/rootfs_linux.go | 42 ++++++++++++++++++++++--------------
1 file changed, 26 insertions(+), 16 deletions(-)

diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go
index e00df0a2..1fc27baf 100644
--- a/libcontainer/rootfs_linux.go
+++ b/libcontainer/rootfs_linux.go
@@ -28,6 +28,12 @@ import (

const defaultMountFlags = unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV

+type mountConfig struct {
+ root string
+ label string
+ cgroupns bool
+}
+
// needsSetupDev returns true if /dev needs to be set up.
func needsSetupDev(config *configs.Config) bool {
for _, m := range config.Mounts {
@@ -47,7 +53,11 @@ func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig) (err error) {
return newSystemErrorWithCause(err, "preparing rootfs")
}

- hasCgroupns := config.Namespaces.Contains(configs.NEWCGROUP)
+ mountConfig := &mountConfig{
+ root: config.Rootfs,
+ label: config.MountLabel,
+ cgroupns: config.Namespaces.Contains(configs.NEWCGROUP),
+ }
setupDev := needsSetupDev(config)
for _, m := range config.Mounts {
for _, precmd := range m.PremountCmds {
@@ -55,7 +65,7 @@ func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig) (err error) {
return newSystemErrorWithCause(err, "running premount command")
}
}
- if err := mountToRootfs(m, config.Rootfs, config.MountLabel, hasCgroupns); err != nil {
+ if err := mountToRootfs(m, mountConfig); err != nil {
return newSystemErrorWithCausef(err, "mounting %q to rootfs at %q", m.Source, m.Destination)
}

@@ -217,7 +227,7 @@ func prepareBindMount(m *configs.Mount, rootfs string) error {
return nil
}

-func mountCgroupV1(m *configs.Mount, rootfs, mountLabel string, enableCgroupns bool) error {
+func mountCgroupV1(m *configs.Mount, c *mountConfig) error {
binds, err := getCgroupMounts(m)
if err != nil {
return err
@@ -237,12 +247,12 @@ func mountCgroupV1(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
Data: "mode=755",
PropagationFlags: m.PropagationFlags,
}
- if err := mountToRootfs(tmpfs, rootfs, mountLabel, enableCgroupns); err != nil {
+ if err := mountToRootfs(tmpfs, c); err != nil {
return err
}
for _, b := range binds {
- if enableCgroupns {
- subsystemPath := filepath.Join(rootfs, b.Destination)
+ if c.cgroupns {
+ subsystemPath := filepath.Join(c.root, b.Destination)
if err := os.MkdirAll(subsystemPath, 0755); err != nil {
return err
}
@@ -261,7 +271,7 @@ func mountCgroupV1(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
return err
}
} else {
- if err := mountToRootfs(b, rootfs, mountLabel, enableCgroupns); err != nil {
+ if err := mountToRootfs(b, c); err != nil {
return err
}
}
@@ -271,7 +281,7 @@ func mountCgroupV1(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
// symlink(2) is very dumb, it will just shove the path into
// the link and doesn't do any checks or relative path
// conversion. Also, don't error out if the cgroup already exists.
- if err := os.Symlink(mc, filepath.Join(rootfs, m.Destination, ss)); err != nil && !os.IsExist(err) {
+ if err := os.Symlink(mc, filepath.Join(c.root, m.Destination, ss)); err != nil && !os.IsExist(err) {
return err
}
}
@@ -279,8 +289,8 @@ func mountCgroupV1(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
return nil
}

-func mountCgroupV2(m *configs.Mount, rootfs, mountLabel string, enableCgroupns bool) error {
- cgroupPath, err := securejoin.SecureJoin(rootfs, m.Destination)
+func mountCgroupV2(m *configs.Mount, c *mountConfig) error {
+ cgroupPath, err := securejoin.SecureJoin(c.root, m.Destination)
if err != nil {
return err
}
@@ -297,10 +307,10 @@ func mountCgroupV2(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
return nil
}

-func mountToRootfs(m *configs.Mount, rootfs, mountLabel string, enableCgroupns bool) error {
- var (
- dest = m.Destination
- )
+func mountToRootfs(m *configs.Mount, c *mountConfig) error {
+ rootfs := c.root
+ mountLabel := c.label
+ dest := m.Destination
if !strings.HasPrefix(dest, rootfs) {
dest = filepath.Join(rootfs, dest)
}
@@ -410,9 +420,9 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
}
case "cgroup":
if cgroups.IsCgroup2UnifiedMode() {
- return mountCgroupV2(m, rootfs, mountLabel, enableCgroupns)
+ return mountCgroupV2(m, c)
}
- return mountCgroupV1(m, rootfs, mountLabel, enableCgroupns)
+ return mountCgroupV1(m, c)
default:
// ensure that the destination of the mount is resolved of symlinks at mount time because
// any previous mounts can invalidate the next mount's destination.
--
2.31.1

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
From 40250b23e808803ed1d1132fac67a87e7663d3f3 Mon Sep 17 00:00:00 2001
Message-Id: <40250b23e808803ed1d1132fac67a87e7663d3f3.1620832610.git.dongsu@kinvolk.io>
In-Reply-To: <7b2b5e4ca66c5c020848f2fd0d3335a2bb8bec95.1620832610.git.dongsu@kinvolk.io>
References: <7b2b5e4ca66c5c020848f2fd0d3335a2bb8bec95.1620832610.git.dongsu@kinvolk.io>
From: Kir Kolyshkin <kolyshkin@gmail.com>
Date: Tue, 23 Feb 2021 18:25:56 -0800
Subject: [PATCH 3/5] libct/rootfs/mountCgroupV2: minor refactor

1. s/cgroupPath/dest/

2. don't hardcode /sys/fs/cgroup

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
---
libcontainer/rootfs_linux.go | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go
index 1fc27baf..7ff576d0 100644
--- a/libcontainer/rootfs_linux.go
+++ b/libcontainer/rootfs_linux.go
@@ -17,6 +17,7 @@ import (
"github.com/moby/sys/mountinfo"
"github.com/mrunalp/fileutils"
"github.com/opencontainers/runc/libcontainer/cgroups"
+ "github.com/opencontainers/runc/libcontainer/cgroups/fs2"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/system"
libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils"
@@ -290,17 +291,18 @@ func mountCgroupV1(m *configs.Mount, c *mountConfig) error {
}

func mountCgroupV2(m *configs.Mount, c *mountConfig) error {
- cgroupPath, err := securejoin.SecureJoin(c.root, m.Destination)
+ dest, err := securejoin.SecureJoin(c.root, m.Destination)
if err != nil {
return err
}
- if err := os.MkdirAll(cgroupPath, 0755); err != nil {
+ if err := os.MkdirAll(dest, 0755); err != nil {
return err
}
- if err := unix.Mount(m.Source, cgroupPath, "cgroup2", uintptr(m.Flags), m.Data); err != nil {
+ if err := unix.Mount(m.Source, dest, "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 {
- return unix.Mount("/sys/fs/cgroup", cgroupPath, "", uintptr(m.Flags)|unix.MS_BIND, "")
+ src := fs2.UnifiedMountpoint
+ return unix.Mount(src, dest, "", uintptr(m.Flags)|unix.MS_BIND, "")
}
return err
}
--
2.31.1

Loading

0 comments on commit 6e0acb8

Please sign in to comment.