diff --git a/CVE-2019-16884.patch b/CVE-2019-16884.patch index 14d309f..2831278 100644 --- a/CVE-2019-16884.patch +++ b/CVE-2019-16884.patch @@ -1,40 +1,79 @@ -From 331692baa7afdf6c186f8667cb0e6362ea0802b3 Mon Sep 17 00:00:00 2001 -From: Michael Crosby +From 6ce3791ce27128f8b4ae45323effa10953fa9904 Mon Sep 17 00:00:00 2001 +From: Aleksa Sarai Date: Mon, 23 Sep 2019 16:45:45 -0400 -Subject: [PATCH] Only allow proc mount if it is procfs +Subject: [PATCH] CVE-2019-16884 -Fixes #2128 +This patch includes a squash of the following upstream patches: -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. + * 331692baa7af ("Only allow proc mount if it is procfs") -```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. +As well as the following still-in-review patches: -> 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 -``` + * ("apparmor: verify that writes to /proc/... are on procfs") + * ("selinux: verify that writes to /proc/... are on procfs") Signed-off-by: Michael Crosby +Signed-off-by: Aleksa Sarai --- - libcontainer/container_linux.go | 4 +-- - libcontainer/rootfs_linux.go | 50 +++++++++++++++++++++++-------- - libcontainer/rootfs_linux_test.go | 8 ++--- - 3 files changed, 43 insertions(+), 19 deletions(-) + libcontainer/apparmor/apparmor.go | 18 ++++++- + libcontainer/container_linux.go | 4 +- + libcontainer/rootfs_linux.go | 50 ++++++++++++++----- + libcontainer/rootfs_linux_test.go | 8 +-- + .../selinux/go-selinux/selinux_linux.go | 20 ++++++++ + 5 files changed, 79 insertions(+), 21 deletions(-) +diff --git a/libcontainer/apparmor/apparmor.go b/libcontainer/apparmor/apparmor.go +index 7fff0627fa1b..3504b80d8643 100644 +--- a/libcontainer/apparmor/apparmor.go ++++ b/libcontainer/apparmor/apparmor.go +@@ -6,6 +6,8 @@ import ( + "fmt" + "io/ioutil" + "os" ++ ++ "golang.org/x/sys/unix" + ) + + // IsEnabled returns true if apparmor is enabled for the host. +@@ -19,7 +21,13 @@ func IsEnabled() bool { + return false + } + +-func setprocattr(attr, value string) error { ++func isProcHandle(fh *os.File) (bool, error) { ++ var buf unix.Statfs_t ++ err := unix.Fstatfs(int(fh.Fd()), &buf) ++ return buf.Type == unix.PROC_SUPER_MAGIC, err ++} ++ ++func setProcAttr(attr, value string) error { + // Under AppArmor you can only change your own attr, so use /proc/self/ + // instead of /proc// like libapparmor does + path := fmt.Sprintf("/proc/self/attr/%s", attr) +@@ -30,6 +38,12 @@ func setprocattr(attr, value string) error { + } + defer f.Close() + ++ if ok, err := isProcHandle(f); err != nil { ++ return err ++ } else if !ok { ++ return fmt.Errorf("/proc path not on procfs: %s", path) ++ } ++ + _, err = fmt.Fprintf(f, "%s", value) + return err + } +@@ -37,7 +51,7 @@ func setprocattr(attr, value string) error { + // changeOnExec reimplements aa_change_onexec from libapparmor in Go + func changeOnExec(name string) error { + value := "exec " + name +- if err := setprocattr("exec", value); err != nil { ++ if err := setProcAttr("exec", value); err != nil { + return fmt.Errorf("apparmor failed to apply profile: %s", err) + } + return nil diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go -index 092792040f5b..6ff4d96a5f55 100644 +index 7e58e5e00824..d51e35dffb93 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -19,7 +19,7 @@ import ( @@ -46,7 +85,7 @@ index 092792040f5b..6ff4d96a5f55 100644 "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 { +@@ -1160,7 +1160,7 @@ func (c *linuxContainer) makeCriuRestoreMountpoints(m *configs.Mount) error { if err != nil { return err } @@ -56,7 +95,7 @@ index 092792040f5b..6ff4d96a5f55 100644 } m.Destination = dest diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go -index 1513c1d94b63..10888b499beb 100644 +index f13b226e444e..5650b0acbca8 100644 --- a/libcontainer/rootfs_linux.go +++ b/libcontainer/rootfs_linux.go @@ -13,7 +13,7 @@ import ( @@ -77,7 +116,7 @@ index 1513c1d94b63..10888b499beb 100644 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 +@@ -388,7 +388,7 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b if dest, err = securejoin.SecureJoin(rootfs, m.Destination); err != nil { return err } @@ -86,7 +125,7 @@ index 1513c1d94b63..10888b499beb 100644 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) { +@@ -435,12 +435,12 @@ func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) { return binds, nil } @@ -104,7 +143,7 @@ index 1513c1d94b63..10888b499beb 100644 // 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 { +@@ -463,16 +463,40 @@ func checkMountDestination(rootfs, dest string) error { return nil } } @@ -190,6 +229,58 @@ index d755984bc0f9..1bfe7c663225 100644 if err != nil { t.Fatal(err) } +diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go +index d7786c33c197..611df8f9b3b0 100644 +--- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go ++++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go +@@ -18,6 +18,8 @@ import ( + "strings" + "sync" + "syscall" ++ ++ "golang.org/x/sys/unix" + ) + + const ( +@@ -252,6 +254,12 @@ func getSELinuxPolicyRoot() string { + return filepath.Join(selinuxDir, readConfig(selinuxTypeTag)) + } + ++func isProcHandle(fh *os.File) (bool, error) { ++ var buf unix.Statfs_t ++ err := unix.Fstatfs(int(fh.Fd()), &buf) ++ return buf.Type == unix.PROC_SUPER_MAGIC, err ++} ++ + func readCon(fpath string) (string, error) { + if fpath == "" { + return "", ErrEmptyPath +@@ -263,6 +271,12 @@ func readCon(fpath string) (string, error) { + } + defer in.Close() + ++ if ok, err := isProcHandle(in); err != nil { ++ return "", err ++ } else if !ok { ++ return "", fmt.Errorf("/proc path not on procfs: %s", fpath) ++ } ++ + var retval string + if _, err := fmt.Fscanf(in, "%s", &retval); err != nil { + return "", err +@@ -345,6 +359,12 @@ func writeCon(fpath string, val string) error { + } + defer out.Close() + ++ if ok, err := isProcHandle(out); err != nil { ++ return err ++ } else if !ok { ++ return fmt.Errorf("/proc path not on procfs: %s", fpath) ++ } ++ + if val != "" { + _, err = out.Write([]byte(val)) + } else { -- 2.23.0 diff --git a/runc.spec b/runc.spec index 8be01b7..8511a50 100644 --- a/runc.spec +++ b/runc.spec @@ -51,7 +51,9 @@ Source0: https://github.com/opencontainers/runc/releases/download/v%{_ver Source1: https://github.com/opencontainers/runc/releases/download/v%{_version}/runc.tar.xz.asc#/runc-%{_version}.tar.xz.asc Source2: runc.keyring Source3: runc-rpmlintrc -# FIX-UPSTREAM: Backport of https://github.com/opencontainers/runc/pull/2129. CVE-2019-16884 +# FIX-UPSTREAM: Backport of https://github.com/opencontainers/runc/pull/2129. +# https://github.com/opencontainers/selinux/pull/59. +# https://github.com/opencontainers/runc/pull/2130. CVE-2019-16884 Patch1: CVE-2019-16884.patch BuildRequires: fdupes BuildRequires: go-go-md2man @@ -95,9 +97,9 @@ Test package for runc. It contains the source code and the tests. # some point during the build and you need to directly use go list directly it # will get confused by symlinks. export GOPATH=${HOME}/go -mkdir -pv $HOME/go/src/%project +mkdir -p $HOME/go/src/%project rm -rf $HOME/go/src/%project/* -cp -av * $HOME/go/src/%project +cp -a * $HOME/go/src/%project # Additionally enable seccomp. %if 0%{?with_libseccomp} @@ -118,7 +120,7 @@ EOF source ./.runc_build_env # Build runc. -make -C "$HOME/go/src/%project" EXTRA_FLAGS="-x $BUILDFLAGS" BUILDTAGS="$BUILDTAGS" COMMIT_NO="%{git_version}" runc +make -C "$HOME/go/src/%project" EXTRA_FLAGS="$BUILDFLAGS" BUILDTAGS="$BUILDTAGS" COMMIT_NO="%{git_version}" runc mv "$HOME/go/src/%project/runc" %{name}-%{version} # Build man pages, this can only be done on arches where we can build go-md2man.