From f5ad6904207702484943372e61664eb49e3e1ab4 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Sep 10 2019 10:39:52 +0000 Subject: import runc-1.0.0-56.rc8.dev.git425e105.module+el8.0.0+4017+bbba319f --- diff --git a/.gitignore b/.gitignore index abc4b4f..4d97e7f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/runc-2abd837.tar.gz +SOURCES/runc-425e105.tar.gz diff --git a/.runc.metadata b/.runc.metadata index 93b3f44..1ff52c1 100644 --- a/.runc.metadata +++ b/.runc.metadata @@ -1 +1 @@ -cf7119a838db2963e7af6ecdba90a2cc95ec0d56 SOURCES/runc-2abd837.tar.gz +cfbe1abc984f5b0be1413475f888e39304b265ae SOURCES/runc-425e105.tar.gz diff --git a/SOURCES/0001-Revert-Apply-cgroups-earlier.patch b/SOURCES/0001-Revert-Apply-cgroups-earlier.patch deleted file mode 100644 index 4ad310a..0000000 --- a/SOURCES/0001-Revert-Apply-cgroups-earlier.patch +++ /dev/null @@ -1,62 +0,0 @@ -From dfb3496c174377b860b62872ce6af951364cc3ac Mon Sep 17 00:00:00 2001 -From: Lokesh Mandvekar -Date: Tue, 12 Dec 2017 13:22:42 +0530 -Subject: [PATCH] Revert "Apply cgroups earlier" - -This reverts commit 7062c7556b71188abc18d7516441ff4b03fbc1fc. ---- - libcontainer/process_linux.go | 31 ++++++++++++++----------------- - 1 file changed, 14 insertions(+), 17 deletions(-) - -diff --git a/libcontainer/process_linux.go b/libcontainer/process_linux.go -index 149b1126..b8a395af 100644 ---- a/libcontainer/process_linux.go -+++ b/libcontainer/process_linux.go -@@ -272,6 +272,20 @@ func (p *initProcess) start() error { - p.process.ops = nil - return newSystemErrorWithCause(err, "starting init process command") - } -+ if _, err := io.Copy(p.parentPipe, p.bootstrapData); err != nil { -+ return newSystemErrorWithCause(err, "copying bootstrap data to pipe") -+ } -+ if err := p.execSetns(); err != nil { -+ return newSystemErrorWithCause(err, "running exec setns process for init") -+ } -+ // Save the standard descriptor names before the container process -+ // can potentially move them (e.g., via dup2()). If we don't do this now, -+ // we won't know at checkpoint time which file descriptor to look up. -+ fds, err := getPipeFds(p.pid()) -+ if err != nil { -+ return newSystemErrorWithCausef(err, "getting pipe fds for pid %d", p.pid()) -+ } -+ p.setExternalDescriptors(fds) - // Do this before syncing with child so that no children can escape the - // cgroup. We don't need to worry about not doing this and not being root - // because we'd be using the rootless cgroup manager in that case. -@@ -292,23 +306,6 @@ func (p *initProcess) start() error { - } - } - }() -- -- if _, err := io.Copy(p.parentPipe, p.bootstrapData); err != nil { -- return newSystemErrorWithCause(err, "copying bootstrap data to pipe") -- } -- -- if err := p.execSetns(); err != nil { -- return newSystemErrorWithCause(err, "running exec setns process for init") -- } -- -- // Save the standard descriptor names before the container process -- // can potentially move them (e.g., via dup2()). If we don't do this now, -- // we won't know at checkpoint time which file descriptor to look up. -- fds, err := getPipeFds(p.pid()) -- if err != nil { -- return newSystemErrorWithCausef(err, "getting pipe fds for pid %d", p.pid()) -- } -- p.setExternalDescriptors(fds) - if err := p.createNetworkInterfaces(); err != nil { - return newSystemErrorWithCause(err, "creating network interfaces") - } --- -2.14.3 - diff --git a/SOURCES/0001-nsenter-clone-proc-self-exe-to-avoid-exposing-host-b-runc.patch b/SOURCES/0001-nsenter-clone-proc-self-exe-to-avoid-exposing-host-b-runc.patch deleted file mode 100644 index 7975703..0000000 --- a/SOURCES/0001-nsenter-clone-proc-self-exe-to-avoid-exposing-host-b-runc.patch +++ /dev/null @@ -1,290 +0,0 @@ -From bf6405284aa3870a39b402309003633a1c230ed9 Mon Sep 17 00:00:00 2001 -From: Aleksa Sarai -Date: Wed, 9 Jan 2019 13:40:01 +1100 -Subject: [PATCH 1/1] nsenter: clone /proc/self/exe to avoid exposing host - binary to container - -There are quite a few circumstances where /proc/self/exe pointing to a -pretty important container binary is a _bad_ thing, so to avoid this we -have to make a copy (preferably doing self-clean-up and not being -writeable). - -As a hotfix we require memfd_create(2), but we can always extend this to -use a scratch MNT_DETACH overlayfs or tmpfs. The main downside to this -approach is no page-cache sharing for the runc binary (which overlayfs -would give us) but this is far less complicated. - -This is only done during nsenter so that it happens transparently to the -Go code, and any libcontainer users benefit from it. This also makes -ExtraFiles and --preserve-fds handling trivial (because we don't need to -worry about it). - -Fixes: CVE-2019-5736 -Co-developed-by: Christian Brauner -Signed-off-by: Aleksa Sarai -Signed-off-by: Mrunal Patel ---- - libcontainer/nsenter/cloned_binary.c | 221 +++++++++++++++++++++++++++ - libcontainer/nsenter/nsexec.c | 11 ++ - 2 files changed, 232 insertions(+) - create mode 100644 libcontainer/nsenter/cloned_binary.c - -diff --git a/libcontainer/nsenter/cloned_binary.c b/libcontainer/nsenter/cloned_binary.c -new file mode 100644 -index 00000000..d9f6093a ---- /dev/null -+++ b/libcontainer/nsenter/cloned_binary.c -@@ -0,0 +1,221 @@ -+#define _GNU_SOURCE -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* Use our own wrapper for memfd_create. */ -+#if !defined(SYS_memfd_create) && defined(__NR_memfd_create) -+# define SYS_memfd_create __NR_memfd_create -+#endif -+#ifndef SYS_memfd_create -+# error "memfd_create(2) syscall not supported by this glibc version" -+#endif -+int memfd_create(const char *name, unsigned int flags) -+{ -+ return syscall(SYS_memfd_create, name, flags); -+} -+ -+/* This comes directly from . */ -+#ifndef F_LINUX_SPECIFIC_BASE -+# define F_LINUX_SPECIFIC_BASE 1024 -+#endif -+#ifndef F_ADD_SEALS -+# define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) -+# define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) -+#endif -+#ifndef F_SEAL_SEAL -+# define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */ -+# define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */ -+# define F_SEAL_GROW 0x0004 /* prevent file from growing */ -+# define F_SEAL_WRITE 0x0008 /* prevent writes */ -+#endif -+ -+ -+#define OUR_MEMFD_COMMENT "runc_cloned:/proc/self/exe" -+#define OUR_MEMFD_SEALS \ -+ (F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE) -+ -+static void *must_realloc(void *ptr, size_t size) -+{ -+ void *old = ptr; -+ do { -+ ptr = realloc(old, size); -+ } while(!ptr); -+ return ptr; -+} -+ -+/* -+ * Verify whether we are currently in a self-cloned program (namely, is -+ * /proc/self/exe a memfd). F_GET_SEALS will only succeed for memfds (or rather -+ * for shmem files), and we want to be sure it's actually sealed. -+ */ -+static int is_self_cloned(void) -+{ -+ int fd, seals; -+ -+ fd = open("/proc/self/exe", O_RDONLY|O_CLOEXEC); -+ if (fd < 0) -+ return -ENOTRECOVERABLE; -+ -+ seals = fcntl(fd, F_GET_SEALS); -+ close(fd); -+ return seals == OUR_MEMFD_SEALS; -+} -+ -+/* -+ * Basic wrapper around mmap(2) that gives you the file length so you can -+ * safely treat it as an ordinary buffer. Only gives you read access. -+ */ -+static char *read_file(char *path, size_t *length) -+{ -+ int fd; -+ char buf[4096], *copy = NULL; -+ -+ if (!length) -+ return NULL; -+ -+ fd = open(path, O_RDONLY | O_CLOEXEC); -+ if (fd < 0) -+ return NULL; -+ -+ *length = 0; -+ for (;;) { -+ int n; -+ -+ n = read(fd, buf, sizeof(buf)); -+ if (n < 0) -+ goto error; -+ if (!n) -+ break; -+ -+ copy = must_realloc(copy, (*length + n) * sizeof(*copy)); -+ memcpy(copy + *length, buf, n); -+ *length += n; -+ } -+ close(fd); -+ return copy; -+ -+error: -+ close(fd); -+ free(copy); -+ return NULL; -+} -+ -+/* -+ * A poor-man's version of "xargs -0". Basically parses a given block of -+ * NUL-delimited data, within the given length and adds a pointer to each entry -+ * to the array of pointers. -+ */ -+static int parse_xargs(char *data, int data_length, char ***output) -+{ -+ int num = 0; -+ char *cur = data; -+ -+ if (!data || *output != NULL) -+ return -1; -+ -+ while (cur < data + data_length) { -+ num++; -+ *output = must_realloc(*output, (num + 1) * sizeof(**output)); -+ (*output)[num - 1] = cur; -+ cur += strlen(cur) + 1; -+ } -+ (*output)[num] = NULL; -+ return num; -+} -+ -+/* -+ * "Parse" out argv and envp from /proc/self/cmdline and /proc/self/environ. -+ * This is necessary because we are running in a context where we don't have a -+ * main() that we can just get the arguments from. -+ */ -+static int fetchve(char ***argv, char ***envp) -+{ -+ char *cmdline = NULL, *environ = NULL; -+ size_t cmdline_size, environ_size; -+ -+ cmdline = read_file("/proc/self/cmdline", &cmdline_size); -+ if (!cmdline) -+ goto error; -+ environ = read_file("/proc/self/environ", &environ_size); -+ if (!environ) -+ goto error; -+ -+ if (parse_xargs(cmdline, cmdline_size, argv) <= 0) -+ goto error; -+ if (parse_xargs(environ, environ_size, envp) <= 0) -+ goto error; -+ -+ return 0; -+ -+error: -+ free(environ); -+ free(cmdline); -+ return -EINVAL; -+} -+ -+#define SENDFILE_MAX 0x7FFFF000 /* sendfile(2) is limited to 2GB. */ -+static int clone_binary(void) -+{ -+ int binfd, memfd, err; -+ ssize_t sent = 0; -+ -+ memfd = memfd_create(OUR_MEMFD_COMMENT, MFD_CLOEXEC | MFD_ALLOW_SEALING); -+ if (memfd < 0) -+ return -ENOTRECOVERABLE; -+ -+ binfd = open("/proc/self/exe", O_RDONLY | O_CLOEXEC); -+ if (binfd < 0) -+ goto error; -+ -+ sent = sendfile(memfd, binfd, NULL, SENDFILE_MAX); -+ close(binfd); -+ if (sent < 0) -+ goto error; -+ -+ err = fcntl(memfd, F_ADD_SEALS, OUR_MEMFD_SEALS); -+ if (err < 0) -+ goto error; -+ -+ return memfd; -+ -+error: -+ close(memfd); -+ return -EIO; -+} -+ -+int ensure_cloned_binary(void) -+{ -+ int execfd; -+ char **argv = NULL, **envp = NULL; -+ -+ /* Check that we're not self-cloned, and if we are then bail. */ -+ int cloned = is_self_cloned(); -+ if (cloned > 0 || cloned == -ENOTRECOVERABLE) -+ return cloned; -+ -+ if (fetchve(&argv, &envp) < 0) -+ return -EINVAL; -+ -+ execfd = clone_binary(); -+ if (execfd < 0) -+ return -EIO; -+ -+ fexecve(execfd, argv, envp); -+ return -ENOEXEC; -+} -diff --git a/libcontainer/nsenter/nsexec.c b/libcontainer/nsenter/nsexec.c -index cb224314..784fd9b0 100644 ---- a/libcontainer/nsenter/nsexec.c -+++ b/libcontainer/nsenter/nsexec.c -@@ -528,6 +528,9 @@ void join_namespaces(char *nslist) - free(namespaces); - } - -+/* Defined in cloned_binary.c. */ -+int ensure_cloned_binary(void); -+ - void nsexec(void) - { - int pipenum; -@@ -543,6 +546,14 @@ void nsexec(void) - if (pipenum == -1) - return; - -+ /* -+ * We need to re-exec if we are not in a cloned binary. This is necessary -+ * to ensure that containers won't be able to access the host binary -+ * through /proc/self/exe. See CVE-2019-5736. -+ */ -+ if (ensure_cloned_binary() < 0) -+ bail("could not ensure we are a cloned binary"); -+ - /* Parse all of the netlink configuration. */ - nl_parse(pipenum, &config); - --- -2.20.1 - diff --git a/SOURCES/1807.patch b/SOURCES/1807.patch index 4f46e89..8cadfa9 100644 --- a/SOURCES/1807.patch +++ b/SOURCES/1807.patch @@ -1,168 +1,179 @@ -From ecf53c23545092019602578583031c28fde4d2a1 Mon Sep 17 00:00:00 2001 +From e3b37893afa498ef6254cc9d94c159b12e04d0b0 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Fri, 25 May 2018 18:04:06 +0200 Subject: [PATCH] sd-notify: do not hang when NOTIFY_SOCKET is used with create if NOTIFY_SOCKET is used, do not block the main runc process waiting -for events on the notify socket. Change the logic to create a new -process that monitors exclusively the notify socket until an event is -received. +for events on the notify socket. Bind mount the parent directory of +the notify socket, so that "start" can create the socket and it is +still accessible from the container. Signed-off-by: Giuseppe Scrivano --- - init.go | 12 +++++++ - notify_socket.go | 101 ++++++++++++++++++++++++++++++++++++++++++++++--------- - signals.go | 5 +-- - 3 files changed, 99 insertions(+), 19 deletions(-) + notify_socket.go | 113 ++++++++++++++++++++++++++++++++++------------- + signals.go | 4 +- + start.go | 13 +++++- + utils_linux.go | 12 ++++- + 4 files changed, 106 insertions(+), 36 deletions(-) -diff --git a/init.go b/init.go -index c8f453192..6a3d9e91c 100644 ---- a/init.go -+++ b/init.go -@@ -20,6 +20,18 @@ var initCommand = cli.Command{ - Name: "init", - Usage: `initialize the namespaces and launch the process (do not call it outside of runc)`, - Action: func(context *cli.Context) error { -+ // If NOTIFY_SOCKET is used create a new process that stays around -+ // so to not block "runc start". It will automatically exits when the -+ // container notifies that it is ready, or when the container is deleted -+ if os.Getenv("_NOTIFY_SOCKET_FD") != "" { -+ fd := os.Getenv("_NOTIFY_SOCKET_FD") -+ pid := os.Getenv("_NOTIFY_SOCKET_PID") -+ hostNotifySocket := os.Getenv("_NOTIFY_SOCKET_HOST") -+ notifySocketPath := os.Getenv("_NOTIFY_SOCKET_PATH") -+ notifySocketInit(fd, pid, hostNotifySocket, notifySocketPath) -+ os.Exit(0) -+ } -+ - factory, _ := libcontainer.New("") - if err := factory.StartInitialization(); err != nil { - // as the error is sent back to the parent there is no need to log diff --git a/notify_socket.go b/notify_socket.go -index cd6c0a989..e04e9d660 100644 +index b890b5b1c..286ce1ddd 100644 --- a/notify_socket.go +++ b/notify_socket.go -@@ -6,10 +6,13 @@ import ( +@@ -6,11 +6,14 @@ import ( "bytes" "fmt" "net" + "os" -+ "os/exec" ++ "path" "path/filepath" + "strconv" + "time" ++ "github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runtime-spec/specs-go" - - "github.com/sirupsen/logrus" +- "github.com/sirupsen/logrus" "github.com/urfave/cli" ) -@@ -64,24 +67,94 @@ func (s *notifySocket) setupSocket() error { + +@@ -26,12 +29,12 @@ func newNotifySocket(context *cli.Context, notifySocketHost string, id string) * + } + + root := filepath.Join(context.GlobalString("root"), id) +- path := filepath.Join(root, "notify.sock") ++ socketPath := filepath.Join(root, "notify", "notify.sock") + + notifySocket := ¬ifySocket{ + socket: nil, + host: notifySocketHost, +- socketPath: path, ++ socketPath: socketPath, + } + + return notifySocket +@@ -43,13 +46,19 @@ func (s *notifySocket) Close() error { + + // If systemd is supporting sd_notify protocol, this function will add support + // for sd_notify protocol from within the container. +-func (s *notifySocket) setupSpec(context *cli.Context, spec *specs.Spec) { +- mount := specs.Mount{Destination: s.host, Source: s.socketPath, Options: []string{"bind"}} ++func (s *notifySocket) setupSpec(context *cli.Context, spec *specs.Spec) error { ++ pathInContainer := filepath.Join("/run/notify", path.Base(s.socketPath)) ++ mount := specs.Mount{ ++ Destination: path.Dir(pathInContainer), ++ Source: path.Dir(s.socketPath), ++ Options: []string{"bind", "nosuid", "noexec", "nodev", "ro"}, ++ } + spec.Mounts = append(spec.Mounts, mount) +- spec.Process.Env = append(spec.Process.Env, fmt.Sprintf("NOTIFY_SOCKET=%s", s.host)) ++ spec.Process.Env = append(spec.Process.Env, fmt.Sprintf("NOTIFY_SOCKET=%s", pathInContainer)) ++ return nil + } + +-func (s *notifySocket) setupSocket() error { ++func (s *notifySocket) bindSocket() error { + addr := net.UnixAddr{ + Name: s.socketPath, + Net: "unixgram", +@@ -64,45 +73,89 @@ func (s *notifySocket) setupSocket() error { return nil } -+func (notifySocket *notifySocket) notifyNewPid(pid int) { -+ notifySocketHostAddr := net.UnixAddr{Name: notifySocket.host, Net: "unixgram"} -+ client, err := net.DialUnix("unixgram", nil, ¬ifySocketHostAddr) -+ if err != nil { -+ return -+ } -+ newPid := fmt.Sprintf("MAINPID=%d\n", pid) -+ client.Write([]byte(newPid)) -+} -+ - // pid1 must be set only with -d, as it is used to set the new process as the main process - // for the service in systemd - func (notifySocket *notifySocket) run(pid1 int) { +-// pid1 must be set only with -d, as it is used to set the new process as the main process +-// for the service in systemd +-func (s *notifySocket) run(pid1 int) { - buf := make([]byte, 512) -- notifySocketHostAddr := net.UnixAddr{Name: notifySocket.host, Net: "unixgram"} -- client, err := net.DialUnix("unixgram", nil, ¬ifySocketHostAddr) -+ file, err := notifySocket.socket.File() - if err != nil { - logrus.Error(err) - return - } -- for { -- r, err := notifySocket.socket.Read(buf) -- if err != nil { -- break -+ defer file.Close() -+ defer notifySocket.socket.Close() +- notifySocketHostAddr := net.UnixAddr{Name: s.host, Net: "unixgram"} ++func (s *notifySocket) setupSocketDirectory() error { ++ return os.Mkdir(path.Dir(s.socketPath), 0755) ++} + -+ cmd := exec.Command("/proc/self/exe", "init") -+ cmd.ExtraFiles = []*os.File{file} -+ cmd.Env = append(cmd.Env, "_NOTIFY_SOCKET_FD=3", -+ fmt.Sprintf("_NOTIFY_SOCKET_PID=%d", pid1), -+ fmt.Sprintf("_NOTIFY_SOCKET_HOST=%s", notifySocket.host), -+ fmt.Sprintf("_NOTIFY_SOCKET_PATH=%s", notifySocket.socketPath)) ++func notifySocketStart(context *cli.Context, notifySocketHost, id string) (*notifySocket, error) { ++ notifySocket := newNotifySocket(context, notifySocketHost, id) ++ if notifySocket == nil { ++ return nil, nil ++ } + -+ if err := cmd.Start(); err != nil { -+ logrus.Fatal(err) ++ if err := notifySocket.bindSocket(); err != nil { ++ return nil, err + } -+ notifySocket.notifyNewPid(cmd.Process.Pid) -+ cmd.Process.Release() ++ return notifySocket, nil +} + -+func notifySocketInit(envFd string, envPid string, notifySocketHost string, notifySocketPath string) { -+ intFd, err := strconv.Atoi(envFd) ++func (n *notifySocket) waitForContainer(container libcontainer.Container) error { ++ s, err := container.State() + if err != nil { -+ return ++ return err + } -+ pid1, err := strconv.Atoi(envPid) -+ if err != nil { -+ return ++ return n.run(s.InitProcessPid) ++} ++ ++func (n *notifySocket) run(pid1 int) error { ++ if n.socket == nil { ++ return nil + } ++ notifySocketHostAddr := net.UnixAddr{Name: n.host, Net: "unixgram"} + client, err := net.DialUnix("unixgram", nil, ¬ifySocketHostAddr) + if err != nil { +- logrus.Error(err) +- return ++ return err + } +- for { +- r, err := s.socket.Read(buf) +- if err != nil { +- break + -+ file := os.NewFile(uintptr(intFd), "unixgram") -+ defer file.Close() ++ ticker := time.NewTicker(time.Millisecond * 100) ++ defer ticker.Stop() + + fileChan := make(chan []byte) -+ exitChan := make(chan bool) -+ + go func() { + for { + buf := make([]byte, 512) -+ r, err := file.Read(buf) ++ r, err := n.socket.Read(buf) + if err != nil { + return + } -+ fileChan <- buf[0:r] ++ got := buf[0:r] ++ if !bytes.HasPrefix(got, []byte("READY=")) { ++ continue ++ } ++ fileChan <- got ++ return } - var out bytes.Buffer - for _, line := range bytes.Split(buf[0:r], []byte{'\n'}) { - if bytes.HasPrefix(line, []byte("READY=")) { + }() -+ go func() { -+ for { -+ if _, err := os.Stat(notifySocketPath); os.IsNotExist(err) { -+ exitChan <- true -+ return -+ } -+ time.Sleep(time.Second) -+ } -+ }() -+ -+ notifySocketHostAddr := net.UnixAddr{Name: notifySocketHost, Net: "unixgram"} -+ client, err := net.DialUnix("unixgram", nil, ¬ifySocketHostAddr) -+ if err != nil { -+ return -+ } + + for { + select { -+ case <-exitChan: -+ return ++ case <-ticker.C: ++ _, err := os.Stat(filepath.Join("/proc", strconv.Itoa(pid1))) ++ if err != nil { ++ return nil ++ } + case b := <-fileChan: + for _, line := range bytes.Split(b, []byte{'\n'}) { -+ if !bytes.HasPrefix(line, []byte("READY=")) { -+ continue -+ } -+ + var out bytes.Buffer _, err = out.Write(line) if err != nil { - return -@@ -98,10 +171,8 @@ func (notifySocket *notifySocket) run(pid1 int) { +- return ++ return err + } + + _, err = out.Write([]byte{'\n'}) + if err != nil { +- return ++ return err + } + + _, err = client.Write(out.Bytes()) + if err != nil { +- return ++ return err } // now we can inform systemd to use pid1 as the pid to monitor @@ -170,25 +181,26 @@ index cd6c0a989..e04e9d660 100644 - newPid := fmt.Sprintf("MAINPID=%d\n", pid1) - client.Write([]byte(newPid)) - } +- return + newPid := fmt.Sprintf("MAINPID=%d\n", pid1) + client.Write([]byte(newPid)) - return ++ return nil } } + } diff --git a/signals.go b/signals.go -index 1811de837..d0988cb39 100644 +index b67f65a03..dd25e094c 100644 --- a/signals.go +++ b/signals.go -@@ -70,7 +70,7 @@ func (h *signalHandler) forward(process *libcontainer.Process, tty *tty, detach +@@ -70,6 +70,7 @@ func (h *signalHandler) forward(process *libcontainer.Process, tty *tty, detach h.notifySocket.run(pid1) return 0, nil - } else { -- go h.notifySocket.run(0) -+ h.notifySocket.run(os.Getpid()) } ++ h.notifySocket.run(os.Getpid()) + go h.notifySocket.run(0) } -@@ -98,9 +98,6 @@ func (h *signalHandler) forward(process *libcontainer.Process, tty *tty, detach +@@ -97,9 +98,6 @@ func (h *signalHandler) forward(process *libcontainer.Process, tty *tty, detach // status because we must ensure that any of the go specific process // fun such as flushing pipes are complete before we return. process.Wait() @@ -198,3 +210,68 @@ index 1811de837..d0988cb39 100644 return e.status, nil } } +diff --git a/start.go b/start.go +index 2bb698b20..3a1769a43 100644 +--- a/start.go ++++ b/start.go +@@ -3,6 +3,7 @@ package main + import ( + "errors" + "fmt" ++ "os" + + "github.com/opencontainers/runc/libcontainer" + "github.com/urfave/cli" +@@ -31,7 +32,17 @@ your host.`, + } + switch status { + case libcontainer.Created: +- return container.Exec() ++ notifySocket, err := notifySocketStart(context, os.Getenv("NOTIFY_SOCKET"), container.ID()) ++ if err != nil { ++ return err ++ } ++ if err := container.Exec(); err != nil { ++ return err ++ } ++ if notifySocket != nil { ++ return notifySocket.waitForContainer(container) ++ } ++ return nil + case libcontainer.Stopped: + return errors.New("cannot start a container that has stopped") + case libcontainer.Running: +diff --git a/utils_linux.go b/utils_linux.go +index ce50db145..670c0fcba 100644 +--- a/utils_linux.go ++++ b/utils_linux.go +@@ -406,7 +406,9 @@ func startContainer(context *cli.Context, spec *specs.Spec, action CtAct, criuOp + + notifySocket := newNotifySocket(context, os.Getenv("NOTIFY_SOCKET"), id) + if notifySocket != nil { +- notifySocket.setupSpec(context, spec) ++ if err := notifySocket.setupSpec(context, spec); err != nil { ++ return -1, err ++ } + } + + container, err := createContainer(context, id, spec) +@@ -415,10 +417,16 @@ func startContainer(context *cli.Context, spec *specs.Spec, action CtAct, criuOp + } + + if notifySocket != nil { +- err := notifySocket.setupSocket() ++ err := notifySocket.setupSocketDirectory() + if err != nil { + return -1, err + } ++ if action == CT_ACT_RUN { ++ err := notifySocket.bindSocket() ++ if err != nil { ++ return -1, err ++ } ++ } + } + + // Support on-demand socket activation by passing file descriptors into the container init process. + diff --git a/SOURCES/change-default-root.patch b/SOURCES/change-default-root.patch deleted file mode 100644 index de94424..0000000 --- a/SOURCES/change-default-root.patch +++ /dev/null @@ -1,61 +0,0 @@ -diff --git a/list.go b/list.go -index 0313d8c..328798b 100644 ---- a/list.go -+++ b/list.go -@@ -50,7 +50,7 @@ var listCommand = cli.Command{ - ArgsUsage: ` - - Where the given root is specified via the global option "--root" --(default: "/run/runc"). -+(default: "/run/runc-ctrs"). - - EXAMPLE 1: - To list containers created via the default "--root": -diff --git a/main.go b/main.go -index 278399a..0f49fce 100644 ---- a/main.go -+++ b/main.go -@@ -62,7 +62,7 @@ func main() { - v = append(v, fmt.Sprintf("spec: %s", specs.Version)) - app.Version = strings.Join(v, "\n") - -- root := "/run/runc" -+ root := "/run/runc-ctrs" - rootless, err := isRootless(nil) - if err != nil { - fatal(err) -@@ -70,7 +70,7 @@ func main() { - if rootless { - runtimeDir := os.Getenv("XDG_RUNTIME_DIR") - if runtimeDir != "" { -- root = runtimeDir + "/runc" -+ root = runtimeDir + "/runc-ctrs" - // According to the XDG specification, we need to set anything in - // XDG_RUNTIME_DIR to have a sticky bit if we don't want it to get - // auto-pruned. -diff --git a/man/runc-list.8.md b/man/runc-list.8.md -index f737424..107220e 100644 ---- a/man/runc-list.8.md -+++ b/man/runc-list.8.md -@@ -6,7 +6,7 @@ - - # EXAMPLE - Where the given root is specified via the global option "--root" --(default: "/run/runc"). -+(default: "/run/runc-ctrs"). - - To list containers created via the default "--root": - # runc list -diff --git a/man/runc.8.md b/man/runc.8.md -index 6d0ddff..337bc73 100644 ---- a/man/runc.8.md -+++ b/man/runc.8.md -@@ -51,7 +51,7 @@ value for "bundle" is the current directory. - --debug enable debug output for logging - --log value set the log file path where internal debug information is written (default: "/dev/null") - --log-format value set the format used by logs ('text' (default), or 'json') (default: "text") -- --root value root directory for storage of container state (this should be located in tmpfs) (default: "/run/runc" or $XDG_RUNTIME_DIR/runc for rootless containers) -+ --root value root directory for storage of container state (this should be located in tmpfs) (default: "/run/runc-ctrs" or $XDG_RUNTIME_DIR/runc-ctrs for rootless containers) - --criu value path to the criu binary used for checkpoint and restore (default: "criu") - --systemd-cgroup enable systemd cgroup support, expects cgroupsPath to be of form "slice:prefix:name" for e.g. "system.slice:runc:434234" - --rootless value enable rootless mode ('true', 'false', or 'auto') (default: "auto") diff --git a/SOURCES/pivot-root.patch b/SOURCES/pivot-root.patch deleted file mode 100644 index 16679df..0000000 --- a/SOURCES/pivot-root.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 28a697cce3e4f905dca700eda81d681a30eef9cd Mon Sep 17 00:00:00 2001 -From: Giuseppe Scrivano -Date: Fri, 11 Jan 2019 21:53:45 +0100 -Subject: [PATCH] rootfs: umount all procfs and sysfs with --no-pivot - -When creating a new user namespace, the kernel doesn't allow to mount -a new procfs or sysfs file system if there is not already one instance -fully visible in the current mount namespace. - -When using --no-pivot we were effectively inhibiting this protection -from the kernel, as /proc and /sys from the host are still present in -the container mount namespace. - -A container without full access to /proc could then create a new user -namespace, and from there able to mount a fully visible /proc, bypassing -the limitations in the container. - -A simple reproducer for this issue is: - -unshare -mrfp sh -c "mount -t proc none /proc && echo c > /proc/sysrq-trigger" - -Signed-off-by: Giuseppe Scrivano ---- - libcontainer/rootfs_linux.go | 35 +++++++++++++++++++++++++++++++++++ - 1 file changed, 35 insertions(+) - -diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go -index e7c2f8ada..6bd6da74a 100644 ---- a/libcontainer/rootfs_linux.go -+++ b/libcontainer/rootfs_linux.go -@@ -748,6 +748,41 @@ func pivotRoot(rootfs string) error { - } - - func msMoveRoot(rootfs string) error { -+ mountinfos, err := mount.GetMounts() -+ if err != nil { -+ return err -+ } -+ -+ absRootfs, err := filepath.Abs(rootfs) -+ if err != nil { -+ return err -+ } -+ -+ for _, info := range mountinfos { -+ p, err := filepath.Abs(info.Mountpoint) -+ if err != nil { -+ return err -+ } -+ // Umount every syfs and proc file systems, except those under the container rootfs -+ if (info.Fstype != "proc" && info.Fstype != "sysfs") || filepath.HasPrefix(p, absRootfs) { -+ continue -+ } -+ // Be sure umount events are not propagated to the host. -+ if err := unix.Mount("", p, "", unix.MS_SLAVE|unix.MS_REC, ""); err != nil { -+ return err -+ } -+ if err := unix.Unmount(p, unix.MNT_DETACH); err != nil { -+ if err != unix.EINVAL && err != unix.EPERM { -+ return err -+ } else { -+ // If we have not privileges for umounting (e.g. rootless), then -+ // cover the path. -+ if err := unix.Mount("tmpfs", p, "tmpfs", 0, ""); err != nil { -+ return err -+ } -+ } -+ } -+ } - if err := unix.Mount(rootfs, "/", "", unix.MS_MOVE, ""); err != nil { - return err - } diff --git a/SPECS/runc.spec b/SPECS/runc.spec index e191f47..48e142b 100644 --- a/SPECS/runc.spec +++ b/SPECS/runc.spec @@ -22,23 +22,25 @@ go build -buildmode pie -compiler gc -tags="rpm_crashtraceback no_openssl ${BUIL %global provider_prefix %{provider}.%{provider_tld}/%{project}/%{repo} %global import_path %{provider_prefix} %global git0 https://github.com/opencontainers/runc -%global commit0 2abd837c8c25b0102ac4ce14f17bc0bc7ddffba7 +%global commit0 425e105d5a03fabd737a126ad93d62a9eeede87f %global shortcommit0 %(c=%{commit0}; echo ${c:0:7}) Name: %{repo} Version: 1.0.0 -Release: 55.rc5.dev.git%{shortcommit0}%{?dist} +Release: 56.rc8.dev.git%{shortcommit0}%{?dist} Summary: CLI for running Open Containers ExcludeArch: %{ix86} License: ASL 2.0 URL: http//%{provider_prefix} Source0: %{git0}/archive/%{commit0}/%{repo}-%{shortcommit0}.tar.gz Source1: 99-containers.conf -Patch0: change-default-root.patch -Patch1: 0001-Revert-Apply-cgroups-earlier.patch +#Patch0: change-default-root.patch +#Patch1: 0001-Revert-Apply-cgroups-earlier.patch Patch2: 1807.patch -Patch3: 0001-nsenter-clone-proc-self-exe-to-avoid-exposing-host-b-runc.patch -Patch4: pivot-root.patch +#Patch3: 0001-nsenter-clone-proc-self-exe-to-avoid-exposing-host-b-runc.patch +#Patch4: pivot-root.patch +#Patch5: bz1743163.patch +#Patch6: bz1743163-2.patch Requires: criu Requires(pre): container-selinux >= 2:2.2-2 @@ -97,6 +99,9 @@ install -p -m 0644 contrib/completions/bash/%{name} %{buildroot}%{_datadir}/bash %{_datadir}/bash-completion/completions/%{name} %changelog +* Mon Aug 19 2019 Lokesh Mandvekar - 1.0.0-56.rc8.dev.git425e105 +- Resolves: #1743163 + * Tue Feb 12 2019 Lokesh Mandvekar - 1.0.0-55.rc5.dev.git2abd837 - Resolves: CVE-2019-5736