From 5fbf791e31201384b84a9b5ca8f03e3d1f45985f Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Mon, 22 Feb 2016 15:36:12 -0500 Subject: [PATCH] Create unique session key name for every container Create a unique session key name for every container. Use the pattern _ses. with postfix being the container's Id. This patch does not prevent containers from joining each other's session keyring. Signed-off-by: Stefan Berger --- libcontainer/container_linux.go | 1 + libcontainer/init_linux.go | 1 + libcontainer/setns_init_linux.go | 7 ++++++- libcontainer/standard_init_linux.go | 25 +++++++++++++++++++++---- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index 284e15ec3..253ef00af 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -324,6 +324,7 @@ func (c *linuxContainer) newInitConfig(process *Process) *initConfig { Console: process.consolePath, Capabilities: process.Capabilities, PassedFilesCount: len(process.ExtraFiles), + ContainerId: c.ID(), } } diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index 918f10301..d442cbf07 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -53,6 +53,7 @@ type initConfig struct { Console string `json:"console"` Networks []*network `json:"network"` PassedFilesCount int `json:"passed_files_count"` + ContainerId string `json:"containerid"` } type initer interface { diff --git a/libcontainer/setns_init_linux.go b/libcontainer/setns_init_linux.go index 29f5b26e0..de356bce8 100644 --- a/libcontainer/setns_init_linux.go +++ b/libcontainer/setns_init_linux.go @@ -3,6 +3,7 @@ package libcontainer import ( + "fmt" "os" "github.com/opencontainers/runc/libcontainer/apparmor" @@ -18,9 +19,13 @@ type linuxSetnsInit struct { config *initConfig } +func (l *linuxSetnsInit) getSessionRingName() string { + return fmt.Sprintf("_ses.%s", l.config.ContainerId) +} + func (l *linuxSetnsInit) Init() error { // do not inherit the parent's session keyring - if _, err := keyctl.JoinSessionKeyring("_ses"); err != nil { + if _, err := keyctl.JoinSessionKeyring(l.getSessionRingName()); err != nil { return err } if err := setupRlimits(l.config.Config); err != nil { diff --git a/libcontainer/standard_init_linux.go b/libcontainer/standard_init_linux.go index 6240347aa..f8cc03f9f 100644 --- a/libcontainer/standard_init_linux.go +++ b/libcontainer/standard_init_linux.go @@ -3,6 +3,7 @@ package libcontainer import ( + "fmt" "io" "os" "syscall" @@ -21,20 +22,36 @@ type linuxStandardInit struct { config *initConfig } +func (l *linuxStandardInit) getSessionRingParams() (string, uint32, uint32) { + var newperms uint32 + + if l.config.Config.Namespaces.Contains(configs.NEWUSER) { + // with user ns we need 'other' search permissions + newperms = 0x8 + } else { + // without user ns we need 'UID' search permissions + newperms = 0x80000 + } + + // create a unique per session container name that we can + // join in setns; however, other containers can also join it + return fmt.Sprintf("_ses.%s", l.config.ContainerId), 0xffffffff, newperms +} + // 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 { + ringname, keepperms, newperms := l.getSessionRingParams() + // do not inherit the parent's session keyring - sessKeyId, err := keyctl.JoinSessionKeyring("") + sessKeyId, err := keyctl.JoinSessionKeyring(ringname) if err != nil { return err } // make session keyring searcheable - // without user ns we need 'UID' search permissions - // with user ns we need 'other' search permissions - if err := keyctl.ModKeyringPerm(sessKeyId, 0xffffffff, 0x080008); err != nil { + if err := keyctl.ModKeyringPerm(sessKeyId, keepperms, newperms); err != nil { return err }