From aa3fee6c80f2817d47e912372267c74a96cde2bd Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Thu, 7 Jun 2018 13:52:01 -0400 Subject: [PATCH] SELinux labels are tied to the thread We need to lock the threads for the SetProcessLabel to work, should also call SetProcessLabel("") after the container starts to go back to the default SELinux behaviour. Once you call SetProcessLabel, then any process executed by runc will run with this label, even if the process is for setup rather then the container. It is always safest to call the SELinux calls just before the exec of the container, so that other processes do not get started with the incorrect label. Signed-off-by: Daniel J Walsh --- libcontainer/setns_init_linux.go | 11 ++++++++--- libcontainer/standard_init_linux.go | 10 +++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/libcontainer/setns_init_linux.go b/libcontainer/setns_init_linux.go index 096c601e..024fba85 100644 --- a/libcontainer/setns_init_linux.go +++ b/libcontainer/setns_init_linux.go @@ -5,6 +5,7 @@ package libcontainer import ( "fmt" "os" + "runtime" "github.com/opencontainers/runc/libcontainer/apparmor" "github.com/opencontainers/runc/libcontainer/keys" @@ -28,6 +29,9 @@ func (l *linuxSetnsInit) getSessionRingName() string { } func (l *linuxSetnsInit) Init() error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + if !l.config.Config.NoNewKeyring { // do not inherit the parent's session keyring if _, err := keys.JoinSessionKeyring(l.getSessionRingName()); err != nil { @@ -47,6 +51,10 @@ func (l *linuxSetnsInit) Init() error { return err } } + if err := label.SetProcessLabel(l.config.ProcessLabel); err != nil { + return err + } + defer label.SetProcessLabel("") // Without NoNewPrivileges seccomp is a privileged operation, so we need to // do this before dropping capabilities; otherwise do it as late as possible // just before execve so as few syscalls take place after it as possible. @@ -61,9 +69,6 @@ func (l *linuxSetnsInit) Init() error { if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil { return err } - if err := label.SetProcessLabel(l.config.ProcessLabel); err != nil { - return err - } // Set seccomp as close to execve as possible, so as few syscalls take // place afterward (reducing the amount of syscalls that users need to // enable in their seccomp profiles). diff --git a/libcontainer/standard_init_linux.go b/libcontainer/standard_init_linux.go index 0b6530d6..9def8d1e 100644 --- a/libcontainer/standard_init_linux.go +++ b/libcontainer/standard_init_linux.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "os/exec" + "runtime" "syscall" //only for Exec "github.com/opencontainers/runc/libcontainer/apparmor" @@ -44,6 +45,8 @@ func (l *linuxStandardInit) getSessionRingParams() (string, uint32, uint32) { } func (l *linuxStandardInit) Init() error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() if !l.config.Config.NoNewKeyring { ringname, keepperms, newperms := l.getSessionRingParams() @@ -96,9 +99,6 @@ func (l *linuxStandardInit) Init() error { if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil { return errors.Wrap(err, "apply apparmor profile") } - if err := label.SetProcessLabel(l.config.ProcessLabel); err != nil { - return errors.Wrap(err, "set process label") - } for key, value := range l.config.Config.Sysctl { if err := writeSystemProperty(key, value); err != nil { @@ -130,6 +130,10 @@ func (l *linuxStandardInit) Init() error { if err := syncParentReady(l.pipe); err != nil { return errors.Wrap(err, "sync ready") } + if err := label.SetProcessLabel(l.config.ProcessLabel); err != nil { + return errors.Wrap(err, "set process label") + } + defer label.SetProcessLabel("") // Without NoNewPrivileges seccomp is a privileged operation, so we need to // do this before dropping capabilities; otherwise do it as late as possible // just before execve so as few syscalls take place after it as possible.