diff --git a/SOURCES/0001-Only-drop-all-caps-in-exec-when-non-root.patch b/SOURCES/0001-Only-drop-all-caps-in-exec-when-non-root.patch new file mode 100644 index 0000000..62f7ae9 --- /dev/null +++ b/SOURCES/0001-Only-drop-all-caps-in-exec-when-non-root.patch @@ -0,0 +1,31 @@ +From fbc96cdd1741021f3d18e49eac3757297aaba851 Mon Sep 17 00:00:00 2001 +From: Matthew Heon +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 +--- + 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_conmon_linux.go ++++ b/libpod/oci_conmon_linux.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 + diff --git a/SOURCES/podman-CVE-2021-20188.patch b/SOURCES/podman-CVE-2021-20188.patch new file mode 100644 index 0000000..19e9888 --- /dev/null +++ b/SOURCES/podman-CVE-2021-20188.patch @@ -0,0 +1,186 @@ +From 764a4df7a35bacc693076afbe3679d0bfce503f5 Mon Sep 17 00:00:00 2001 +From: Matthew Heon +Date: Thu, 21 Jan 2021 16:22:32 -0500 +Subject: [PATCH] Restrict caps of non-root processes in priv containers + +Non-root processes in privileged containers do not get all caps, +and instead only have Bounding and Inherited set to all; the +other caps are left empty. This behavior matches Docker and newer +Podman releases. + +Addresses CVE-2021-20188 + +Signed-off-by: Matthew Heon +--- + libpod/container_api.go | 11 ++++------- + libpod/oci.go | 4 ++-- + libpod/oci_conmon_linux.go | 31 ++++++++++++++++++++++++------- + pkg/spec/spec.go | 8 ++++++++ + 4 files changed, 38 insertions(+), 16 deletions(-) + +diff --git a/libpod/container_api.go b/libpod/container_api.go +index 6d19bd85e..0c57d5678 100644 +--- a/libpod/container_api.go ++++ b/libpod/container_api.go +@@ -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" +@@ -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() +@@ -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() +@@ -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 +@@ -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 +diff --git a/libpod/oci.go b/libpod/oci.go +index 05a2f37db..559c1f59e 100644 +--- a/libpod/oci.go ++++ b/libpod/oci.go +@@ -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. +@@ -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 + } +diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go +index 0b8decd31..d5973a1a6 100644 +--- a/libpod/oci_conmon_linux.go ++++ b/libpod/oci_conmon_linux.go +@@ -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" +@@ -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 + } +@@ -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") + } +@@ -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 +@@ -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=") { +diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go +index 86d701f7e..b313b6695 100644 +--- a/pkg/spec/spec.go ++++ b/pkg/spec/spec.go +@@ -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 +-- +2.29.2 + diff --git a/SPECS/podman.spec b/SPECS/podman.spec index de3abd0..f44a3ad 100644 --- a/SPECS/podman.spec +++ b/SPECS/podman.spec @@ -30,9 +30,9 @@ Name: podman Version: 1.6.4 -Release: 27%{?dist} +Release: 29%{?dist} Summary: Manage Pods, Containers and Container Images -ExcludeArch: s390 ppc ppc64 +ExcludeArch: %{ix86} s390 ppc ppc64 License: ASL 2.0 URL: https://%{name}.io/ Source0: %{git0}/archive/%{commit0}/%{repo}-%{shortcommit0}.tar.gz @@ -78,6 +78,11 @@ Patch14: podman-1877699.patch # patch: 0001-Fix-CVE-2020-14370.patch Patch15: podman-CVE-2020-14370.patch Patch16: podman-1895027.patch +# tracker bug: https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2021-20188 +# patch: 0001-Restrict-caps-of-non-root-processes-in-priv-containe.patch +Patch17: podman-CVE-2021-20188.patch +# related bug: https://bugzilla.redhat.com/show_bug.cgi?id=1930552 +Patch18: 0001-Only-drop-all-caps-in-exec-when-non-root.patch Provides: %{name}-manpages = %{version}-%{release} Obsoletes: %{name}-manpages < %{version}-%{release} %if 0%{?rhel} <= 7 && ! 0%{?fedora} @@ -381,6 +386,14 @@ exit 0 %{_datadir}/%{name}/test %changelog +* Mon Feb 22 2021 Jindrich Novy - 1.6.4-29 +- fix "podman can not create user inside of container" +- Related: #1930552 + +* Mon Feb 15 2021 Jindrich Novy - 1.6.4-28 +- fix "CVE-2021-20188 podman: container users permissions are not respected in privileged containers [rhel-7.9.z]" +- Resolves: #1918282 + * Thu Dec 10 2020 Jindrich Novy - 1.6.4-27 - fix podman-buildah mounting issue - Resolves: #1895027