From 61bfcfd82a937d318c9fabfd7fec3b3d54d06292 Mon Sep 17 00:00:00 2001 From: Mrunal Patel Date: Tue, 16 Feb 2016 03:54:58 -0800 Subject: [PATCH 1/3] Add libcontainer configuration for NoNewPrivileges Signed-off-by: Mrunal Patel --- libcontainer/configs/config.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libcontainer/configs/config.go b/libcontainer/configs/config.go index 069daae2..f6a163b7 100644 --- a/libcontainer/configs/config.go +++ b/libcontainer/configs/config.go @@ -171,6 +171,9 @@ type Config struct { // A default action to be taken if no rules match is also given. Seccomp *Seccomp `json:"seccomp"` + // NoNewPrivileges controls whether processes in the container can gain additional privileges. + NoNewPrivileges bool `json:"no_new_privileges"` + // Hooks are a collection of actions to perform at various container lifecycle events. // Hooks are not able to be marshaled to json but they are also not needed to. Hooks *Hooks `json:"-"` From 38b39645d97db973481423a93f3078a58b55d81a Mon Sep 17 00:00:00 2001 From: Mrunal Patel Date: Tue, 16 Feb 2016 03:55:26 -0800 Subject: [PATCH 2/3] Implement NoNewPrivileges support in libcontainer Signed-off-by: Mrunal Patel --- libcontainer/setns_init_linux.go | 5 +++++ libcontainer/standard_init_linux.go | 10 ++++++++++ libcontainer/system/linux.go | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/libcontainer/setns_init_linux.go b/libcontainer/setns_init_linux.go index cb9af7d7..29f5b26e 100644 --- a/libcontainer/setns_init_linux.go +++ b/libcontainer/setns_init_linux.go @@ -29,6 +29,11 @@ func (l *linuxSetnsInit) Init() error { if err := setOomScoreAdj(l.config.Config.OomScoreAdj); err != nil { return err } + if l.config.Config.NoNewPrivileges { + if err := system.Prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil { + return err + } + } if l.config.Config.Seccomp != nil { if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil { return err diff --git a/libcontainer/standard_init_linux.go b/libcontainer/standard_init_linux.go index c17031dc..6240347a 100644 --- a/libcontainer/standard_init_linux.go +++ b/libcontainer/standard_init_linux.go @@ -21,6 +21,10 @@ type linuxStandardInit struct { config *initConfig } +// PR_SET_NO_NEW_PRIVS isn't exposed in Golang so we define it ourselves copying the value +// the kernel +const PR_SET_NO_NEW_PRIVS = 0x26 + func (l *linuxStandardInit) Init() error { // do not inherit the parent's session keyring sessKeyId, err := keyctl.JoinSessionKeyring("") @@ -103,6 +107,11 @@ func (l *linuxStandardInit) Init() error { if err != nil { return err } + if l.config.Config.NoNewPrivileges { + if err := system.Prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil { + return err + } + } // Tell our parent that we're ready to Execv. This must be done before the // Seccomp rules have been applied, because we need to be able to read and // write to a socket. @@ -128,5 +137,6 @@ func (l *linuxStandardInit) Init() error { if syscall.Getppid() != l.parentPid { return syscall.Kill(syscall.Getpid(), syscall.SIGKILL) } + return system.Execv(l.config.Args[0], l.config.Args[0:], os.Environ()) } diff --git a/libcontainer/system/linux.go b/libcontainer/system/linux.go index 6c835e68..babf5504 100644 --- a/libcontainer/system/linux.go +++ b/libcontainer/system/linux.go @@ -112,3 +112,11 @@ func RunningInUserNS() bool { } return true } + +func Prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) { + _, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0) + if e1 != 0 { + err = e1 + } + return +} From af400b90c387302e07e9c48f8467a1058c903a05 Mon Sep 17 00:00:00 2001 From: Mrunal Patel Date: Tue, 16 Feb 2016 03:55:53 -0800 Subject: [PATCH 3/3] Hook up the support to the OCI specification config Signed-off-by: Mrunal Patel --- spec.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec.go b/spec.go index 2836e7c8..9c482b5c 100644 --- a/spec.go +++ b/spec.go @@ -140,6 +140,7 @@ var specCommand = cli.Command{ Soft: uint64(1024), }, }, + NoNewPrivileges: true, }, } @@ -300,6 +301,7 @@ func createLibcontainerConfig(cgroupName string, spec *specs.LinuxSpec) (*config config.Sysctl = spec.Linux.Sysctl config.ProcessLabel = spec.Linux.SelinuxProcessLabel config.AppArmorProfile = spec.Linux.ApparmorProfile + config.NoNewPrivileges = spec.Linux.NoNewPrivileges for _, g := range spec.Process.User.AdditionalGids { config.AdditionalGroups = append(config.AdditionalGroups, strconv.FormatUint(uint64(g), 10)) }