From e18de631089118a9eb958e65c94cb723b589adaf Mon Sep 17 00:00:00 2001 From: Justin Cormack Date: Wed, 27 Apr 2016 16:15:58 +0100 Subject: [PATCH] If possible, apply seccomp rules immediately before exec See https://github.com/docker/docker/issues/22252 Previously we would apply seccomp rules before applying capabilities, because it requires CAP_SYS_ADMIN. This however means that a seccomp profile needs to allow operations such as setcap() and setuid() which you might reasonably want to disallow. If prctl(PR_SET_NO_NEW_PRIVS) has been applied however setting a seccomp filter is an unprivileged operation. Therefore if this has been set, apply the seccomp filter as late as possible, after capabilities have been dropped and the uid set. Note a small number of syscalls will take place after the filter is applied, such as `futex`, `stat` and `execve`, so these still need to be allowed in addition to any the program itself needs. Signed-off-by: Justin Cormack --- libcontainer/standard_init_linux.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/libcontainer/standard_init_linux.go b/libcontainer/standard_init_linux.go index 59bd3700..5809b4de 100644 --- a/libcontainer/standard_init_linux.go +++ b/libcontainer/standard_init_linux.go @@ -123,7 +123,10 @@ func (l *linuxStandardInit) Init() error { if err := syncParentReady(l.pipe); err != nil { return err } - if l.config.Config.Seccomp != nil { + // 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. + if l.config.Config.Seccomp != nil && !l.config.NoNewPrivileges { if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil { return err } @@ -142,6 +145,11 @@ func (l *linuxStandardInit) Init() error { if syscall.Getppid() != l.parentPid { return syscall.Kill(syscall.Getpid(), syscall.SIGKILL) } + if l.config.Config.Seccomp != nil && l.config.NoNewPrivileges { + if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil { + return err + } + } return system.Execv(l.config.Args[0], l.config.Args[0:], os.Environ()) }