Skip to content

Commit 2c7b579

Browse files
authored
Merge pull request #9305 from mheon/164_cve_2021_20188
[v1.6.4-rhel] Restrict caps of non-root processes in priv containers
2 parents 90ef753 + 764a4df commit 2c7b579

File tree

4 files changed

+38
-16
lines changed

4 files changed

+38
-16
lines changed

libpod/container_api.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"github.com/containers/libpod/libpod/define"
1111
"github.com/containers/libpod/libpod/events"
1212
"github.com/containers/storage/pkg/stringid"
13-
"github.com/docker/docker/oci/caps"
1413
"github.com/opentracing/opentracing-go"
1514
"github.com/pkg/errors"
1615
"github.com/sirupsen/logrus"
@@ -220,7 +219,6 @@ func (c *Container) Kill(signal uint) error {
220219
// Otherwise, the exit code will be the exit code of the executed call inside of the container.
221220
// TODO investigate allowing exec without attaching
222221
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) {
223-
var capList []string
224222
if !c.batched {
225223
c.lock.Lock()
226224
defer c.lock.Unlock()
@@ -234,10 +232,6 @@ func (c *Container) Exec(tty, privileged bool, env map[string]string, cmd []stri
234232
return define.ExecErrorCodeCannotInvoke, errors.Wrapf(define.ErrCtrStateInvalid, "cannot exec into container that is not running")
235233
}
236234

237-
if privileged || c.config.Privileged {
238-
capList = caps.GetAllCapabilities()
239-
}
240-
241235
// Generate exec session ID
242236
// Ensure we don't conflict with an existing session ID
243237
sessionID := stringid.GenerateNonCryptoID()
@@ -270,7 +264,6 @@ func (c *Container) Exec(tty, privileged bool, env map[string]string, cmd []stri
270264

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

276+
if privileged || c.config.Privileged {
277+
opts.Privileged = true
278+
}
279+
283280
pid, attachChan, err := c.ociRuntime.ExecContainer(c, sessionID, opts)
284281
if err != nil {
285282
ec := define.ExecErrorCodeGeneric

libpod/oci.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ type OCIRuntime interface {
105105
type ExecOptions struct {
106106
// Cmd is the command to execute.
107107
Cmd []string
108-
// CapAdd is a set of capabilities to add to the executed command.
109-
CapAdd []string
110108
// Env is a set of environment variables to add to the container.
111109
Env map[string]string
112110
// Terminal is whether to create a new TTY for the exec session.
@@ -129,4 +127,6 @@ type ExecOptions struct {
129127
// DetachKeys is a set of keys that, when pressed in sequence, will
130128
// detach from the container.
131129
DetachKeys string
130+
// Privileged is whether the exec session is privileged.
131+
Privileged bool
132132
}

libpod/oci_conmon_linux.go

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/containers/libpod/utils"
2727
pmount "github.com/containers/storage/pkg/mount"
2828
"github.com/coreos/go-systemd/activation"
29+
"github.com/docker/docker/oci/caps"
2930
spec "github.com/opencontainers/runtime-spec/specs-go"
3031
"github.com/opencontainers/selinux/go-selinux"
3132
"github.com/opencontainers/selinux/go-selinux/label"
@@ -523,7 +524,7 @@ func (r *ConmonOCIRuntime) ExecContainer(c *Container, sessionID string, options
523524
finalEnv = append(finalEnv, fmt.Sprintf("%s=%s", k, v))
524525
}
525526

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

541-
for _, capability := range options.CapAdd {
542-
args = append(args, formatRuntimeOpts("--cap", capability)...)
543-
}
544-
545542
if options.Terminal {
546543
args = append(args, "-t")
547544
}
@@ -1041,12 +1038,15 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
10411038

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

1106+
allCaps := caps.GetAllCapabilities()
1107+
pspec.Capabilities.Effective = []string{}
1108+
if privileged {
1109+
pspec.Capabilities.Bounding = allCaps
1110+
} else {
1111+
pspec.Capabilities.Bounding = []string{}
1112+
}
1113+
pspec.Capabilities.Inheritable = pspec.Capabilities.Bounding
1114+
if execUser.Uid == 0 {
1115+
pspec.Capabilities.Effective = pspec.Capabilities.Bounding
1116+
pspec.Capabilities.Permitted = pspec.Capabilities.Bounding
1117+
pspec.Capabilities.Ambient = pspec.Capabilities.Bounding
1118+
} else {
1119+
pspec.Capabilities.Permitted = pspec.Capabilities.Effective
1120+
pspec.Capabilities.Ambient = pspec.Capabilities.Effective
1121+
}
1122+
11061123
hasHomeSet := false
11071124
for _, s := range pspec.Env {
11081125
if strings.HasPrefix(s, "HOME=") {

pkg/spec/spec.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,14 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
374374
}
375375
} else {
376376
g.SetupPrivileged(true)
377+
if config.User != "" {
378+
user := strings.SplitN(config.User, ":", 2)[0]
379+
if user != "root" && user != "0" {
380+
g.Spec().Process.Capabilities.Effective = []string{}
381+
g.Spec().Process.Capabilities.Permitted = []string{}
382+
g.Spec().Process.Capabilities.Ambient = []string{}
383+
}
384+
}
377385
}
378386

379387
// HANDLE SECCOMP

0 commit comments

Comments
 (0)