import podman-1.0.0-8.git921f98f.module+el8.3.0+10171+12421f43

This commit is contained in:
CentOS Sources 2021-03-03 10:47:45 -05:00 committed by Andrew Lukoshko
parent 89330e0c06
commit 6822973416
3 changed files with 364 additions and 1 deletions

View File

@ -0,0 +1,31 @@
From fbc96cdd1741021f3d18e49eac3757297aaba851 Mon Sep 17 00:00:00 2001
From: Matthew Heon <mheon@redhat.com>
Date: Fri, 19 Feb 2021 11:34:39 -0500
Subject: [PATCH] Only drop all caps in exec when non-root
We were dropping too many capabilities otherwise, which broke
some critical system tools (e.g. useradd) in exec sessions.
Fix RHBZ#1930552
Signed-off-by: Matthew Heon <mheon@redhat.com>
---
libpod/oci_conmon_linux.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index d5973a1a6..18ede031e 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -1107,7 +1107,7 @@ func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, se
pspec.Capabilities.Effective = []string{}
if privileged {
pspec.Capabilities.Bounding = allCaps
- } else {
+ } else if execUser.Uid != 0 {
pspec.Capabilities.Bounding = []string{}
}
pspec.Capabilities.Inheritable = pspec.Capabilities.Bounding
--
2.29.2

View File

@ -0,0 +1,319 @@
From 69daa67c436a8fdeb0149aa5cb0112f03fdb699f Mon Sep 17 00:00:00 2001
From: Matthew Heon <mheon@redhat.com>
Date: Mon, 25 Jan 2021 14:18:07 -0500
Subject: [PATCH] Correct handling of capabilities
Ensure that capabilities are properly handled for non-root users
in privileged containers. We do not want to give full caps, but
instead only CapInh and CapEff (others should be all-zeroes).
Fixing `podman run` is easy - the same code as the Podman 1.6 fix
works there. The `podman exec` command is far more challenging.
Exec received a complete rewrite to use Conmon at some point
before Podman 1.6, and gained many capabilities in the process.
One of those was the ability to actually tweak the capabilities
of the exec process - 1.0 did not have that. Since it was needed
to resolve this CVE, I was forced to backport a large bit of the
1.0 -> 1.6 exec changes (passing a Process block to the OCI
runtime, and using `prepareProcessExec()` to prepare said block).
I am honestly uncomfortable with the size and scope of this
change but I don't see another way around this.
Fixes CVE-2021-20188
Signed-off-by: Matthew Heon <mheon@redhat.com>
---
libpod/container_api.go | 24 +------
libpod/oci.go | 148 ++++++++++++++++++++++++++++++++--------
pkg/spec/spec.go | 8 +++
3 files changed, 132 insertions(+), 48 deletions(-)
diff -up libpod-921f98f8795eb9fcb19ce581020cfdeff6dee09f/libpod/container_api.go.orig libpod-921f98f8795eb9fcb19ce581020cfdeff6dee09f/libpod/container_api.go
--- libpod-921f98f8795eb9fcb19ce581020cfdeff6dee09f/libpod/container_api.go.orig 2019-02-11 16:26:46.000000000 +0100
+++ libpod-921f98f8795eb9fcb19ce581020cfdeff6dee09f/libpod/container_api.go 2021-02-12 10:38:48.767172399 +0100
@@ -2,7 +2,6 @@ package libpod
import (
"context"
- "fmt"
"io/ioutil"
"os"
"strconv"
@@ -11,9 +10,7 @@ import (
"github.com/containers/libpod/libpod/driver"
"github.com/containers/libpod/pkg/inspect"
- "github.com/containers/libpod/pkg/lookup"
"github.com/containers/storage/pkg/stringid"
- "github.com/docker/docker/daemon/caps"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/wait"
@@ -263,8 +260,6 @@ func (c *Container) Kill(signal uint) er
// TODO allow specifying streams to attach to
// TODO investigate allowing exec without attaching
func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir string) error {
- var capList []string
-
locked := false
if !c.batched {
locked = true
@@ -287,22 +282,8 @@ func (c *Container) Exec(tty, privileged
if conState != ContainerStateRunning {
return errors.Errorf("cannot exec into container that is not running")
}
- if privileged || c.config.Privileged {
- capList = caps.GetAllCapabilities()
- }
- // If user was set, look it up in the container to get a UID to use on
- // the host
- hostUser := ""
- if user != "" {
- execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, user, nil)
- if err != nil {
- return err
- }
-
- // runc expects user formatted as uid:gid
- hostUser = fmt.Sprintf("%d:%d", execUser.Uid, execUser.Gid)
- }
+ isPrivileged := privileged || c.config.Privileged
// Generate exec session ID
// Ensure we don't conflict with an existing session ID
@@ -324,10 +305,11 @@ func (c *Container) Exec(tty, privileged
logrus.Debugf("Creating new exec session in container %s with session id %s", c.ID(), sessionID)
- execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, hostUser, sessionID)
+ execCmd, processFile, err := c.runtime.ociRuntime.execContainer(c, cmd, env, tty, workDir, user, sessionID, isPrivileged)
if err != nil {
return errors.Wrapf(err, "error exec %s", c.ID())
}
+ defer os.Remove(processFile)
chWait := make(chan error)
go func() {
chWait <- execCmd.Wait()
diff -up libpod-921f98f8795eb9fcb19ce581020cfdeff6dee09f/libpod/oci.go.orig libpod-921f98f8795eb9fcb19ce581020cfdeff6dee09f/libpod/oci.go
--- libpod-921f98f8795eb9fcb19ce581020cfdeff6dee09f/libpod/oci.go.orig 2019-02-11 16:26:46.000000000 +0100
+++ libpod-921f98f8795eb9fcb19ce581020cfdeff6dee09f/libpod/oci.go 2021-02-12 10:38:48.768172416 +0100
@@ -15,10 +15,12 @@ import (
"syscall"
"time"
+ "github.com/containers/libpod/pkg/lookup"
"github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/util"
"github.com/coreos/go-systemd/activation"
"github.com/cri-o/ocicni/pkg/ocicni"
+ "github.com/docker/docker/daemon/caps"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux"
"github.com/opencontainers/selinux/go-selinux/label"
@@ -735,18 +737,23 @@ func (r *OCIRuntime) unpauseContainer(ct
// TODO: Add --detach support
// TODO: Convert to use conmon
// TODO: add --pid-file and use that to generate exec session tracking
-func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, cwd, user, sessionID string) (*exec.Cmd, error) {
+func (r *OCIRuntime) execContainer(c *Container, cmd, env []string, tty bool, cwd, user, sessionID string, privileged bool) (*exec.Cmd, string, error) {
if len(cmd) == 0 {
- return nil, errors.Wrapf(ErrInvalidArg, "must provide a command to execute")
+ return nil, "", errors.Wrapf(ErrInvalidArg, "must provide a command to execute")
}
if sessionID == "" {
- return nil, errors.Wrapf(ErrEmptyID, "must provide a session ID for exec")
+ return nil, "", errors.Wrapf(ErrEmptyID, "must provide a session ID for exec")
}
runtimeDir, err := util.GetRootlessRuntimeDir()
if err != nil {
- return nil, err
+ return nil, "", err
+ }
+
+ processFile, err := prepareProcessExec(c, cmd, env, tty, cwd, user, sessionID, privileged)
+ if err != nil {
+ return nil, "", err
}
args := []string{}
@@ -756,34 +763,14 @@ func (r *OCIRuntime) execContainer(c *Co
args = append(args, "exec")
- if cwd != "" {
- args = append(args, "--cwd", cwd)
- }
+ args = append(args, "--process", processFile)
args = append(args, "--pid-file", c.execPidPath(sessionID))
- if tty {
- args = append(args, "--tty")
- } else {
- args = append(args, "--tty=false")
- }
-
- if user != "" {
- args = append(args, "--user", user)
- }
-
if c.config.Spec.Process.NoNewPrivileges {
args = append(args, "--no-new-privs")
}
- for _, cap := range capAdd {
- args = append(args, "--cap", cap)
- }
-
- for _, envVar := range env {
- args = append(args, "--env", envVar)
- }
-
// Append container ID and command
args = append(args, c.ID())
args = append(args, cmd...)
@@ -797,10 +784,10 @@ func (r *OCIRuntime) execContainer(c *Co
execCmd.Env = append(execCmd.Env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir))
if err := execCmd.Start(); err != nil {
- return nil, errors.Wrapf(err, "cannot start container %s", c.ID())
+ return nil, "", errors.Wrapf(err, "cannot start container %s", c.ID())
}
- return execCmd, nil
+ return execCmd, processFile, nil
}
// execStopContainer stops all active exec sessions in a container
@@ -892,3 +879,110 @@ func (r *OCIRuntime) checkpointContainer
args = append(args, ctr.ID())
return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, args...)
}
+
+// prepareProcessExec returns the path of the process.json used in runc exec -p.
+// Returns path to the created exec process file. This will need to be removed
+// by the caller when they're done, best effort.
+func prepareProcessExec(c *Container, cmd, env []string, tty bool, cwd, user, sessionID string, privileged bool) (string, error) {
+ filename := filepath.Join(c.bundlePath(), fmt.Sprintf("exec-process-%s", sessionID))
+ f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0600)
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+
+ pspec := c.config.Spec.Process
+ pspec.SelinuxLabel = c.config.ProcessLabel
+ pspec.Args = cmd
+ // We need to default this to false else it will inherit terminal as true
+ // from the container.
+ pspec.Terminal = false
+ if tty {
+ pspec.Terminal = true
+ }
+ if len(env) > 0 {
+ pspec.Env = append(pspec.Env, env...)
+ }
+
+ if cwd != "" {
+ pspec.Cwd = cwd
+
+ }
+
+ var addGroups []string
+ var sgids []uint32
+
+ // if the user is empty, we should inherit the user that the container is currently running with
+ if user == "" {
+ user = c.config.User
+ addGroups = c.config.Groups
+ }
+
+ execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, user, nil)
+ if err != nil {
+ return "", err
+ }
+
+ if len(addGroups) > 0 {
+ sgids, err = lookup.GetContainerGroups(addGroups, c.state.Mountpoint, nil)
+ if err != nil {
+ return "", errors.Wrapf(err, "error looking up supplemental groups for container %s exec session %s", c.ID(), sessionID)
+ }
+ }
+
+ // If user was set, look it up in the container to get a UID to use on
+ // the host
+ if user != "" || len(sgids) > 0 {
+ if user != "" {
+ for _, sgid := range execUser.Sgids {
+ sgids = append(sgids, uint32(sgid))
+ }
+ }
+ processUser := spec.User{
+ UID: uint32(execUser.Uid),
+ GID: uint32(execUser.Gid),
+ AdditionalGids: sgids,
+ }
+
+ 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=") {
+ hasHomeSet = true
+ break
+ }
+ }
+ if !hasHomeSet {
+ pspec.Env = append(pspec.Env, fmt.Sprintf("HOME=%s", execUser.Home))
+ }
+
+ processJSON, err := json.Marshal(pspec)
+ if err != nil {
+ return "", err
+ }
+
+ if err := ioutil.WriteFile(filename, processJSON, 0644); err != nil {
+ return "", err
+ }
+
+ return filename, nil
+}
diff -up libpod-921f98f8795eb9fcb19ce581020cfdeff6dee09f/pkg/spec/spec.go.orig libpod-921f98f8795eb9fcb19ce581020cfdeff6dee09f/pkg/spec/spec.go
--- libpod-921f98f8795eb9fcb19ce581020cfdeff6dee09f/pkg/spec/spec.go.orig 2019-02-11 16:26:46.000000000 +0100
+++ libpod-921f98f8795eb9fcb19ce581020cfdeff6dee09f/pkg/spec/spec.go 2021-02-12 10:38:48.768172416 +0100
@@ -325,6 +325,14 @@ func CreateConfigToOCISpec(config *Creat
}
} 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

View File

@ -36,7 +36,7 @@ go build -buildmode pie -compiler gc -tags="rpm_crashtraceback no_openssl ${BUIL
Name: podman
Version: 1.0.0
Release: 6.git%{shortcommit}%{?dist}
Release: 8.git%{shortcommit}%{?dist}
Summary: Manage Pods, Containers and Container Images
License: ASL 2.0
URL: %{git_podman}
@ -48,6 +48,10 @@ Patch0: podman-CVE-2020-10696.patch
# related bug: https://bugzilla.redhat.com/show_bug.cgi?id=1882267
# patch: https://github.com/mheon/libpod/commit/bc5be3ca10cd4c147955fadd2586b5dd8ad0eeea.patch
Patch1: podman-1882267.patch
# related bug: https://bugzilla.redhat.com/show_bug.cgi?id=1918285
Patch2: podman-CVE-2021-20188.patch
# related bug: https://bugzilla.redhat.com/show_bug.cgi?id=1930552
Patch3: 0001-Only-drop-all-caps-in-exec-when-non-root.patch
# e.g. el6 has ppc64 arch without gcc-go, so EA tag is required
#ExclusiveArch: %%{?go_arches:%%{go_arches}}%%{!?go_arches:%%{ix86} x86_64 aarch64 %%{arm}}
@ -286,6 +290,15 @@ export GOPATH=%{buildroot}/%{gopath}:$(pwd)/vendor:%{gopath}
%{_mandir}/man1/docker*.1*
%changelog
* Mon Mar 01 2021 Jindrich Novy <jnovy@redhat.com> - 1.0.0-8.git921f98f
- fix "podman can not create user inside of container" regression introduced by
patch for CVE-2021-20188
- Related: #1918285
* Fri Feb 12 2021 Jindrich Novy <jnovy@redhat.com> - 1.0.0-7.git921f98f
- fix CVE-2021-20188
- Resolves: #1918285
* Thu Sep 24 2020 Jindrich Novy <jnovy@redhat.com> - 1.0.0-6.git921f98f
- fix "podman run errors out/segfaults in container-tools-1.0-8.3.0"
- Resolves: #1882267