9d89de
From 50a19c6ff828c58e5dab13830bd3dacde268afe5 Mon Sep 17 00:00:00 2001
9d89de
From: Michael Crosby <crosbymichael@gmail.com>
9d89de
Date: Wed, 7 Dec 2016 15:05:51 -0800
9d89de
Subject: [PATCH] Set init processes as non-dumpable
9d89de
9d89de
This sets the init processes that join and setup the container's
9d89de
namespaces as non-dumpable before they setns to the container's pid (or
9d89de
any other ) namespace.
9d89de
9d89de
This settings is automatically reset to the default after the Exec in
9d89de
the container so that it does not change functionality for the
9d89de
applications that are running inside, just our init processes.
9d89de
9d89de
This prevents parent processes, the pid 1 of the container, to ptrace
9d89de
the init process before it drops caps and other sets LSMs.
9d89de
9d89de
This patch also ensures that the stateDirFD being used is still closed
9d89de
prior to exec, even though it is set as O_CLOEXEC, because of the order
9d89de
in the kernel.
9d89de
9d89de
https://github.com/torvalds/linux/blob/v4.9/fs/exec.c#L1290-L1318
9d89de
9d89de
The order during the exec syscall is that the process is set back to
9d89de
dumpable before O_CLOEXEC are processed.
9d89de
9d89de
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
9d89de
---
9d89de
 libcontainer/init_linux.go          | 3 ++-
9d89de
 libcontainer/nsenter/nsexec.c       | 5 +++++
9d89de
 libcontainer/setns_init_linux.go    | 7 ++++++-
9d89de
 libcontainer/standard_init_linux.go | 3 +++
9d89de
 4 files changed, 16 insertions(+), 2 deletions(-)
9d89de
9d89de
diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go
9d89de
index b1e6762..4043d51 100644
9d89de
--- a/libcontainer/init_linux.go
9d89de
+++ b/libcontainer/init_linux.go
9d89de
@@ -77,7 +77,8 @@ func newContainerInit(t initType, pipe *os.File, stateDirFD int) (initer, error)
9d89de
 	switch t {
9d89de
 	case initSetns:
9d89de
 		return &linuxSetnsInit{
9d89de
-			config: config,
9d89de
+			config:     config,
9d89de
+			stateDirFD: stateDirFD,
9d89de
 		}, nil
9d89de
 	case initStandard:
9d89de
 		return &linuxStandardInit{
9d89de
diff --git a/libcontainer/nsenter/nsexec.c b/libcontainer/nsenter/nsexec.c
9d89de
index b93f827..4b5398b 100644
9d89de
--- a/libcontainer/nsenter/nsexec.c
9d89de
+++ b/libcontainer/nsenter/nsexec.c
9d89de
@@ -408,6 +408,11 @@ void nsexec(void)
9d89de
 	if (pipenum == -1)
9d89de
 		return;
9d89de
 
9d89de
+	/* make the process non-dumpable */
9d89de
+	if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) != 0) {
9d89de
+		bail("failed to set process as non-dumpable");
9d89de
+	}
9d89de
+
9d89de
 	/* Parse all of the netlink configuration. */
9d89de
 	nl_parse(pipenum, &config);
9d89de
 
9d89de
diff --git a/libcontainer/setns_init_linux.go b/libcontainer/setns_init_linux.go
9d89de
index 2a8f345..7f5f182 100644
9d89de
--- a/libcontainer/setns_init_linux.go
9d89de
+++ b/libcontainer/setns_init_linux.go
9d89de
@@ -5,6 +5,7 @@ package libcontainer
9d89de
 import (
9d89de
 	"fmt"
9d89de
 	"os"
9d89de
+	"syscall"
9d89de
 
9d89de
 	"github.com/opencontainers/runc/libcontainer/apparmor"
9d89de
 	"github.com/opencontainers/runc/libcontainer/keys"
9d89de
@@ -16,7 +17,8 @@ import (
9d89de
 // linuxSetnsInit performs the container's initialization for running a new process
9d89de
 // inside an existing container.
9d89de
 type linuxSetnsInit struct {
9d89de
-	config *initConfig
9d89de
+	config     *initConfig
9d89de
+	stateDirFD int
9d89de
 }
9d89de
 
9d89de
 func (l *linuxSetnsInit) getSessionRingName() string {
9d89de
@@ -49,5 +51,8 @@ func (l *linuxSetnsInit) Init() error {
9d89de
 	if err := label.SetProcessLabel(l.config.ProcessLabel); err != nil {
9d89de
 		return err
9d89de
 	}
9d89de
+	// close the statedir fd before exec because the kernel resets dumpable in the wrong order
9d89de
+	// https://github.com/torvalds/linux/blob/v4.9/fs/exec.c#L1290-L1318
9d89de
+	syscall.Close(l.stateDirFD)
9d89de
 	return system.Execv(l.config.Args[0], l.config.Args[0:], os.Environ())
9d89de
 }
9d89de
diff --git a/libcontainer/standard_init_linux.go b/libcontainer/standard_init_linux.go
9d89de
index 2104f1a..6a65154 100644
9d89de
--- a/libcontainer/standard_init_linux.go
9d89de
+++ b/libcontainer/standard_init_linux.go
9d89de
@@ -171,6 +171,9 @@ func (l *linuxStandardInit) Init() error {
9d89de
 			return newSystemErrorWithCause(err, "init seccomp")
9d89de
 		}
9d89de
 	}
9d89de
+	// close the statedir fd before exec because the kernel resets dumpable in the wrong order
9d89de
+	// https://github.com/torvalds/linux/blob/v4.9/fs/exec.c#L1290-L1318
9d89de
+	syscall.Close(l.stateDirFD)
9d89de
 	if err := syscall.Exec(name, l.config.Args[0:], os.Environ()); err != nil {
9d89de
 		return newSystemErrorWithCause(err, "exec user process")
9d89de
 	}
9d89de
-- 
9d89de
2.11.0
9d89de