Skip to content

Commit

Permalink
Merge pull request #9305 from mheon/164_cve_2021_20188
Browse files Browse the repository at this point in the history
[v1.6.4-rhel] Restrict caps of non-root processes in priv containers
  • Loading branch information
baude committed Feb 10, 2021
2 parents 90ef753 + 764a4df commit 2c7b579
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 16 deletions.
11 changes: 4 additions & 7 deletions libpod/container_api.go
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/events"
"github.com/containers/storage/pkg/stringid"
"github.com/docker/docker/oci/caps"
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -220,7 +219,6 @@ func (c *Container) Kill(signal uint) error {
// Otherwise, the exit code will be the exit code of the executed call inside of the container.
// TODO investigate allowing exec without attaching
func (c *Container) Exec(tty, privileged bool, env map[string]string, cmd []string, user, workDir string, streams *AttachStreams, preserveFDs uint, resize chan remotecommand.TerminalSize, detachKeys string) (int, error) {
var capList []string
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()
Expand All @@ -234,10 +232,6 @@ func (c *Container) Exec(tty, privileged bool, env map[string]string, cmd []stri
return define.ExecErrorCodeCannotInvoke, errors.Wrapf(define.ErrCtrStateInvalid, "cannot exec into container that is not running")
}

if privileged || c.config.Privileged {
capList = caps.GetAllCapabilities()
}

// Generate exec session ID
// Ensure we don't conflict with an existing session ID
sessionID := stringid.GenerateNonCryptoID()
Expand Down Expand Up @@ -270,7 +264,6 @@ func (c *Container) Exec(tty, privileged bool, env map[string]string, cmd []stri

opts := new(ExecOptions)
opts.Cmd = cmd
opts.CapAdd = capList
opts.Env = env
opts.Terminal = tty
opts.Cwd = workDir
Expand All @@ -280,6 +273,10 @@ func (c *Container) Exec(tty, privileged bool, env map[string]string, cmd []stri
opts.Resize = resize
opts.DetachKeys = detachKeys

if privileged || c.config.Privileged {
opts.Privileged = true
}

pid, attachChan, err := c.ociRuntime.ExecContainer(c, sessionID, opts)
if err != nil {
ec := define.ExecErrorCodeGeneric
Expand Down
4 changes: 2 additions & 2 deletions libpod/oci.go
Expand Up @@ -105,8 +105,6 @@ type OCIRuntime interface {
type ExecOptions struct {
// Cmd is the command to execute.
Cmd []string
// CapAdd is a set of capabilities to add to the executed command.
CapAdd []string
// Env is a set of environment variables to add to the container.
Env map[string]string
// Terminal is whether to create a new TTY for the exec session.
Expand All @@ -129,4 +127,6 @@ type ExecOptions struct {
// DetachKeys is a set of keys that, when pressed in sequence, will
// detach from the container.
DetachKeys string
// Privileged is whether the exec session is privileged.
Privileged bool
}
31 changes: 24 additions & 7 deletions libpod/oci_conmon_linux.go
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/containers/libpod/utils"
pmount "github.com/containers/storage/pkg/mount"
"github.com/coreos/go-systemd/activation"
"github.com/docker/docker/oci/caps"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux"
"github.com/opencontainers/selinux/go-selinux/label"
Expand Down Expand Up @@ -523,7 +524,7 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options
finalEnv = append(finalEnv, fmt.Sprintf("%s=%s", k, v))
}

processFile, err := prepareProcessExec(c, options.Cmd, finalEnv, options.Terminal, options.Cwd, options.User, sessionID)
processFile, err := prepareProcessExec(c, options.Cmd, finalEnv, options.Terminal, options.Cwd, options.User, sessionID, options.Privileged)
if err != nil {
return -1, nil, err
}
Expand All @@ -538,10 +539,6 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options
args = append(args, formatRuntimeOpts("--preserve-fds", fmt.Sprintf("%d", options.PreserveFDs))...)
}

for _, capability := range options.CapAdd {
args = append(args, formatRuntimeOpts("--cap", capability)...)
}

if options.Terminal {
args = append(args, "-t")
}
Expand Down Expand Up @@ -1041,12 +1038,15 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co

// prepareProcessExec returns the path of the process.json used in runc exec -p
// caller is responsible to close the returned *os.File if needed.
func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, sessionID string) (*os.File, error) {
func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, sessionID string, privileged bool) (*os.File, error) {
f, err := ioutil.TempFile(c.execBundlePath(sessionID), "exec-process-")
if err != nil {
return nil, err
}
pspec := c.config.Spec.Process
pspec := new(spec.Process)
if err := JSONDeepCopy(c.config.Spec.Process, pspec); err != nil {
return nil, err
}
pspec.SelinuxLabel = c.config.ProcessLabel
pspec.Args = cmd
// We need to default this to false else it will inherit terminal as true
Expand Down Expand Up @@ -1103,6 +1103,23 @@ func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, se
pspec.User = processUser
}

allCaps := caps.GetAllCapabilities()
pspec.Capabilities.Effective = []string{}
if privileged {
pspec.Capabilities.Bounding = allCaps
} else {
pspec.Capabilities.Bounding = []string{}
}
pspec.Capabilities.Inheritable = pspec.Capabilities.Bounding
if execUser.Uid == 0 {
pspec.Capabilities.Effective = pspec.Capabilities.Bounding
pspec.Capabilities.Permitted = pspec.Capabilities.Bounding
pspec.Capabilities.Ambient = pspec.Capabilities.Bounding
} else {
pspec.Capabilities.Permitted = pspec.Capabilities.Effective
pspec.Capabilities.Ambient = pspec.Capabilities.Effective
}

hasHomeSet := false
for _, s := range pspec.Env {
if strings.HasPrefix(s, "HOME=") {
Expand Down
8 changes: 8 additions & 0 deletions pkg/spec/spec.go
Expand Up @@ -374,6 +374,14 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
}
} else {
g.SetupPrivileged(true)
if config.User != "" {
user := strings.SplitN(config.User, ":", 2)[0]
if user != "root" && user != "0" {
g.Spec().Process.Capabilities.Effective = []string{}
g.Spec().Process.Capabilities.Permitted = []string{}
g.Spec().Process.Capabilities.Ambient = []string{}
}
}
}

// HANDLE SECCOMP
Expand Down

0 comments on commit 2c7b579

Please sign in to comment.