diff --git a/CVE-2019-16884.patch b/CVE-2019-16884.patch index 2831278..0beee43 100644 --- a/CVE-2019-16884.patch +++ b/CVE-2019-16884.patch @@ -1,5 +1,5 @@ -From 6ce3791ce27128f8b4ae45323effa10953fa9904 Mon Sep 17 00:00:00 2001 -From: Aleksa Sarai +From 74e43887d1e124b78c6e29876cff65423b8a999a Mon Sep 17 00:00:00 2001 +From: Michael Crosby Date: Mon, 23 Sep 2019 16:45:45 -0400 Subject: [PATCH] CVE-2019-16884 @@ -9,21 +9,24 @@ This patch includes a squash of the following upstream patches: As well as the following still-in-review patches: - * ("apparmor: verify that writes to /proc/... are on procfs") - * ("selinux: verify that writes to /proc/... are on procfs") + * opencontainers/runc#2130: + ("*: verify that writes to /proc/... are on procfs") + * opencontainers/selinux#59: + ("selinux: verify that writes to /proc/... are on procfs") Signed-off-by: Michael Crosby Signed-off-by: Aleksa Sarai --- - libcontainer/apparmor/apparmor.go | 18 ++++++- + libcontainer/apparmor/apparmor.go | 12 ++++- libcontainer/container_linux.go | 4 +- libcontainer/rootfs_linux.go | 50 ++++++++++++++----- libcontainer/rootfs_linux_test.go | 8 +-- + libcontainer/utils/utils_unix.go | 41 +++++++++++---- .../selinux/go-selinux/selinux_linux.go | 20 ++++++++ - 5 files changed, 79 insertions(+), 21 deletions(-) + 6 files changed, 104 insertions(+), 31 deletions(-) diff --git a/libcontainer/apparmor/apparmor.go b/libcontainer/apparmor/apparmor.go -index 7fff0627fa1b..3504b80d8643 100644 +index 7fff0627fa1b..a482269141b6 100644 --- a/libcontainer/apparmor/apparmor.go +++ b/libcontainer/apparmor/apparmor.go @@ -6,6 +6,8 @@ import ( @@ -31,39 +34,33 @@ index 7fff0627fa1b..3504b80d8643 100644 "io/ioutil" "os" + -+ "golang.org/x/sys/unix" ++ "github.com/opencontainers/runc/libcontainer/utils" ) // IsEnabled returns true if apparmor is enabled for the host. -@@ -19,7 +21,13 @@ func IsEnabled() bool { +@@ -19,7 +21,7 @@ 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 { +@@ -30,6 +32,12 @@ func setprocattr(attr, value string) error { } defer f.Close() -+ if ok, err := isProcHandle(f); err != nil { ++ if ok, err := utils.IsProcHandle(f); err != nil { + return err + } else if !ok { -+ return fmt.Errorf("/proc path not on procfs: %s", path) ++ return fmt.Errorf("%s not on procfs", path) + } + _, err = fmt.Fprintf(f, "%s", value) return err } -@@ -37,7 +51,7 @@ func setprocattr(attr, value string) error { +@@ -37,7 +45,7 @@ func setprocattr(attr, value string) error { // changeOnExec reimplements aa_change_onexec from libapparmor in Go func changeOnExec(name string) error { value := "exec " + name @@ -229,8 +226,77 @@ index d755984bc0f9..1bfe7c663225 100644 if err != nil { t.Fatal(err) } +diff --git a/libcontainer/utils/utils_unix.go b/libcontainer/utils/utils_unix.go +index c96088988a6d..cac37c449c6a 100644 +--- a/libcontainer/utils/utils_unix.go ++++ b/libcontainer/utils/utils_unix.go +@@ -3,33 +3,54 @@ + package utils + + import ( +- "io/ioutil" ++ "fmt" + "os" + "strconv" + + "golang.org/x/sys/unix" + ) + ++// IsProcHandle returns whether or not the given file handle is on procfs. ++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 ++} ++ ++// CloseExecFrom applies O_CLOEXEC to all file descriptors currently open for ++// the process (except for those below the given fd value). + func CloseExecFrom(minFd int) error { +- fdList, err := ioutil.ReadDir("/proc/self/fd") ++ fdDir, err := os.Open("/proc/self/fd") + if err != nil { + return err + } +- for _, fi := range fdList { +- fd, err := strconv.Atoi(fi.Name()) ++ defer fdDir.Close() ++ ++ if ok, err := IsProcHandle(fdDir); err != nil { ++ return err ++ } else if !ok { ++ return fmt.Errorf("/proc/self/fd not on procfs") ++ } ++ ++ fdList, err := fdDir.Readdirnames(-1) ++ if err != nil { ++ return err ++ } ++ for _, fdStr := range fdList { ++ fd, err := strconv.Atoi(fdStr) ++ // Ignore non-numeric file names. + if err != nil { +- // ignore non-numeric file names + continue + } +- ++ // Ignore descriptors lower than our specified minimum. + if fd < minFd { +- // ignore descriptors lower than our specified minimum + continue + } +- +- // intentionally ignore errors from unix.CloseOnExec ++ // Intentionally ignore errors from unix.CloseOnExec -- the cases where ++ // this might fail are basically file descriptors that have already ++ // been closed (including and especially the one that was created when ++ // ioutil.ReadDir did the "opendir" syscall). + unix.CloseOnExec(fd) +- // the cases where this might fail are basically file descriptors that have already been closed (including and especially the one that was created when ioutil.ReadDir did the "opendir" syscall) + } + return nil + } 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 +index d7786c33c197..04e94176daa0 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 ( @@ -262,7 +328,7 @@ index d7786c33c197..611df8f9b3b0 100644 + if ok, err := isProcHandle(in); err != nil { + return "", err + } else if !ok { -+ return "", fmt.Errorf("/proc path not on procfs: %s", fpath) ++ return "", fmt.Errorf("%s not on procfs", fpath) + } + var retval string @@ -275,7 +341,7 @@ index d7786c33c197..611df8f9b3b0 100644 + if ok, err := isProcHandle(out); err != nil { + return err + } else if !ok { -+ return fmt.Errorf("/proc path not on procfs: %s", fpath) ++ return fmt.Errorf("%s not on procfs", fpath) + } + if val != "" {