Accepting request 733478 from home:cyphar:containers:maint
- Add backported fix for CVE-2019-16884. + CVE-2019-16884.patch - Add runc-rpmlintrc to drop runc-test rpmlint warnings. OBS-URL: https://build.opensuse.org/request/show/733478 OBS-URL: https://build.opensuse.org/package/show/Virtualization:containers/runc?expand=0&rev=76
This commit is contained in:
parent
67c52ee2aa
commit
1a94d9d340
195
CVE-2019-16884.patch
Normal file
195
CVE-2019-16884.patch
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
From 331692baa7afdf6c186f8667cb0e6362ea0802b3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Crosby <crosbymichael@gmail.com>
|
||||||
|
Date: Mon, 23 Sep 2019 16:45:45 -0400
|
||||||
|
Subject: [PATCH] Only allow proc mount if it is procfs
|
||||||
|
|
||||||
|
Fixes #2128
|
||||||
|
|
||||||
|
This allows proc to be bind mounted for host and rootless namespace usecases but
|
||||||
|
it removes the ability to mount over the top of proc with a directory.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> sudo docker run --rm apparmor
|
||||||
|
docker: Error response from daemon: OCI runtime create failed:
|
||||||
|
container_linux.go:346: starting container process caused "process_linux.go:449:
|
||||||
|
container init caused \"rootfs_linux.go:58: mounting
|
||||||
|
\\\"/var/lib/docker/volumes/aae28ea068c33d60e64d1a75916cf3ec2dc3634f97571854c9ed30c8401460c1/_data\\\"
|
||||||
|
to rootfs
|
||||||
|
\\\"/var/lib/docker/overlay2/a6be5ae911bf19f8eecb23a295dec85be9a8ee8da66e9fb55b47c841d1e381b7/merged\\\"
|
||||||
|
at \\\"/proc\\\" caused
|
||||||
|
\\\"\\\\\\\"/var/lib/docker/overlay2/a6be5ae911bf19f8eecb23a295dec85be9a8ee8da66e9fb55b47c841d1e381b7/merged/proc\\\\\\\"
|
||||||
|
cannot be mounted because it is not of type proc\\\"\"": unknown.
|
||||||
|
|
||||||
|
> sudo docker run --rm -v /proc:/proc apparmor
|
||||||
|
|
||||||
|
docker-default (enforce) root 18989 0.9 0.0 1288 4 ?
|
||||||
|
Ss 16:47 0:00 sleep 20
|
||||||
|
```
|
||||||
|
|
||||||
|
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
|
||||||
|
---
|
||||||
|
libcontainer/container_linux.go | 4 +--
|
||||||
|
libcontainer/rootfs_linux.go | 50 +++++++++++++++++++++++--------
|
||||||
|
libcontainer/rootfs_linux_test.go | 8 ++---
|
||||||
|
3 files changed, 43 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go
|
||||||
|
index 092792040f5b..6ff4d96a5f55 100644
|
||||||
|
--- a/libcontainer/container_linux.go
|
||||||
|
+++ b/libcontainer/container_linux.go
|
||||||
|
@@ -19,7 +19,7 @@ import (
|
||||||
|
"syscall" // only for SysProcAttr and Signal
|
||||||
|
"time"
|
||||||
|
|
||||||
|
- "github.com/cyphar/filepath-securejoin"
|
||||||
|
+ securejoin "github.com/cyphar/filepath-securejoin"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/configs"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/intelrdt"
|
||||||
|
@@ -1176,7 +1176,7 @@ func (c *linuxContainer) makeCriuRestoreMountpoints(m *configs.Mount) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
- if err := checkMountDestination(c.config.Rootfs, dest); err != nil {
|
||||||
|
+ if err := checkProcMount(c.config.Rootfs, dest, ""); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m.Destination = dest
|
||||||
|
diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go
|
||||||
|
index 1513c1d94b63..10888b499beb 100644
|
||||||
|
--- a/libcontainer/rootfs_linux.go
|
||||||
|
+++ b/libcontainer/rootfs_linux.go
|
||||||
|
@@ -13,7 +13,7 @@ import (
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
- "github.com/cyphar/filepath-securejoin"
|
||||||
|
+ securejoin "github.com/cyphar/filepath-securejoin"
|
||||||
|
"github.com/mrunalp/fileutils"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||||
|
"github.com/opencontainers/runc/libcontainer/configs"
|
||||||
|
@@ -197,7 +197,7 @@ func prepareBindMount(m *configs.Mount, rootfs string) error {
|
||||||
|
if dest, err = securejoin.SecureJoin(rootfs, m.Destination); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
- if err := checkMountDestination(rootfs, dest); err != nil {
|
||||||
|
+ if err := checkProcMount(rootfs, dest, m.Source); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// update the mount with the correct dest after symlinks are resolved.
|
||||||
|
@@ -414,7 +414,7 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
|
||||||
|
if dest, err = securejoin.SecureJoin(rootfs, m.Destination); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
- if err := checkMountDestination(rootfs, dest); err != nil {
|
||||||
|
+ if err := checkProcMount(rootfs, dest, m.Source); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// update the mount with the correct dest after symlinks are resolved.
|
||||||
|
@@ -461,12 +461,12 @@ func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) {
|
||||||
|
return binds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
-// checkMountDestination checks to ensure that the mount destination is not over the top of /proc.
|
||||||
|
+// checkProcMount checks to ensure that the mount destination is not over the top of /proc.
|
||||||
|
// dest is required to be an abs path and have any symlinks resolved before calling this function.
|
||||||
|
-func checkMountDestination(rootfs, dest string) error {
|
||||||
|
- invalidDestinations := []string{
|
||||||
|
- "/proc",
|
||||||
|
- }
|
||||||
|
+//
|
||||||
|
+// if source is nil, don't stat the filesystem. This is used for restore of a checkpoint.
|
||||||
|
+func checkProcMount(rootfs, dest, source string) error {
|
||||||
|
+ const procPath = "/proc"
|
||||||
|
// White list, it should be sub directories of invalid destinations
|
||||||
|
validDestinations := []string{
|
||||||
|
// These entries can be bind mounted by files emulated by fuse,
|
||||||
|
@@ -489,16 +489,40 @@ func checkMountDestination(rootfs, dest string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- for _, invalid := range invalidDestinations {
|
||||||
|
- path, err := filepath.Rel(filepath.Join(rootfs, invalid), dest)
|
||||||
|
+ path, err := filepath.Rel(filepath.Join(rootfs, procPath), dest)
|
||||||
|
+ if err != nil {
|
||||||
|
+ return err
|
||||||
|
+ }
|
||||||
|
+ // pass if the mount path is located outside of /proc
|
||||||
|
+ if strings.HasPrefix(path, "..") {
|
||||||
|
+ return nil
|
||||||
|
+ }
|
||||||
|
+ if path == "." {
|
||||||
|
+ // an empty source is pasted on restore
|
||||||
|
+ if source == "" {
|
||||||
|
+ return nil
|
||||||
|
+ }
|
||||||
|
+ // only allow a mount on-top of proc if it's source is "proc"
|
||||||
|
+ isproc, err := isProc(source)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
- if path != "." && !strings.HasPrefix(path, "..") {
|
||||||
|
- return fmt.Errorf("%q cannot be mounted because it is located inside %q", dest, invalid)
|
||||||
|
+ // pass if the mount is happening on top of /proc and the source of
|
||||||
|
+ // the mount is a proc filesystem
|
||||||
|
+ if isproc {
|
||||||
|
+ return nil
|
||||||
|
}
|
||||||
|
+ return fmt.Errorf("%q cannot be mounted because it is not of type proc", dest)
|
||||||
|
}
|
||||||
|
- return nil
|
||||||
|
+ return fmt.Errorf("%q cannot be mounted because it is inside /proc", dest)
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+func isProc(path string) (bool, error) {
|
||||||
|
+ var s unix.Statfs_t
|
||||||
|
+ if err := unix.Statfs(path, &s); err != nil {
|
||||||
|
+ return false, err
|
||||||
|
+ }
|
||||||
|
+ return s.Type == unix.PROC_SUPER_MAGIC, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupDevSymlinks(rootfs string) error {
|
||||||
|
diff --git a/libcontainer/rootfs_linux_test.go b/libcontainer/rootfs_linux_test.go
|
||||||
|
index d755984bc0f9..1bfe7c663225 100644
|
||||||
|
--- a/libcontainer/rootfs_linux_test.go
|
||||||
|
+++ b/libcontainer/rootfs_linux_test.go
|
||||||
|
@@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
|
func TestCheckMountDestOnProc(t *testing.T) {
|
||||||
|
dest := "/rootfs/proc/sys"
|
||||||
|
- err := checkMountDestination("/rootfs", dest)
|
||||||
|
+ err := checkProcMount("/rootfs", dest, "")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("destination inside proc should return an error")
|
||||||
|
}
|
||||||
|
@@ -18,7 +18,7 @@ func TestCheckMountDestOnProc(t *testing.T) {
|
||||||
|
|
||||||
|
func TestCheckMountDestOnProcChroot(t *testing.T) {
|
||||||
|
dest := "/rootfs/proc/"
|
||||||
|
- err := checkMountDestination("/rootfs", dest)
|
||||||
|
+ err := checkProcMount("/rootfs", dest, "/proc")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("destination inside proc when using chroot should not return an error")
|
||||||
|
}
|
||||||
|
@@ -26,7 +26,7 @@ func TestCheckMountDestOnProcChroot(t *testing.T) {
|
||||||
|
|
||||||
|
func TestCheckMountDestInSys(t *testing.T) {
|
||||||
|
dest := "/rootfs//sys/fs/cgroup"
|
||||||
|
- err := checkMountDestination("/rootfs", dest)
|
||||||
|
+ err := checkProcMount("/rootfs", dest, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("destination inside /sys should not return an error")
|
||||||
|
}
|
||||||
|
@@ -34,7 +34,7 @@ func TestCheckMountDestInSys(t *testing.T) {
|
||||||
|
|
||||||
|
func TestCheckMountDestFalsePositive(t *testing.T) {
|
||||||
|
dest := "/rootfs/sysfiles/fs/cgroup"
|
||||||
|
- err := checkMountDestination("/rootfs", dest)
|
||||||
|
+ err := checkProcMount("/rootfs", dest, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
|
|
2
runc-rpmlintrc
Normal file
2
runc-rpmlintrc
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# -test is something that is used internally and isn't actually shipped -- it's a pseudo-source package.
|
||||||
|
addFilter ("^runc(-kubic)?-test.*")
|
@ -1,3 +1,10 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Sep 26 14:54:07 UTC 2019 - Aleksa Sarai <asarai@suse.com>
|
||||||
|
|
||||||
|
- Add backported fix for CVE-2019-16884.
|
||||||
|
+ CVE-2019-16884.patch
|
||||||
|
- Add runc-rpmlintrc to drop runc-test rpmlint warnings.
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Mon Apr 29 11:56:21 UTC 2019 - Aleksa Sarai <asarai@suse.com>
|
Mon Apr 29 11:56:21 UTC 2019 - Aleksa Sarai <asarai@suse.com>
|
||||||
|
|
||||||
|
@ -50,6 +50,9 @@ Url: https://github.com/opencontainers/runc
|
|||||||
Source0: https://github.com/opencontainers/runc/releases/download/v%{_version}/runc.tar.xz#/runc-%{_version}.tar.xz
|
Source0: https://github.com/opencontainers/runc/releases/download/v%{_version}/runc.tar.xz#/runc-%{_version}.tar.xz
|
||||||
Source1: https://github.com/opencontainers/runc/releases/download/v%{_version}/runc.tar.xz.asc#/runc-%{_version}.tar.xz.asc
|
Source1: https://github.com/opencontainers/runc/releases/download/v%{_version}/runc.tar.xz.asc#/runc-%{_version}.tar.xz.asc
|
||||||
Source2: runc.keyring
|
Source2: runc.keyring
|
||||||
|
Source3: runc-rpmlintrc
|
||||||
|
# FIX-UPSTREAM: Backport of https://github.com/opencontainers/runc/pull/2129. CVE-2019-16884
|
||||||
|
Patch1: CVE-2019-16884.patch
|
||||||
BuildRequires: fdupes
|
BuildRequires: fdupes
|
||||||
BuildRequires: go-go-md2man
|
BuildRequires: go-go-md2man
|
||||||
BuildRequires: golang(API) = %{go_version}
|
BuildRequires: golang(API) = %{go_version}
|
||||||
@ -84,6 +87,8 @@ Test package for runc. It contains the source code and the tests.
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n %{name}-%{_version}
|
%setup -q -n %{name}-%{_version}
|
||||||
|
# CVE-2019-16884
|
||||||
|
%patch1 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
# Do not use symlinks. If you want to run the unit tests for this package at
|
# Do not use symlinks. If you want to run the unit tests for this package at
|
||||||
|
Loading…
Reference in New Issue
Block a user