aboutsummaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container_exec.go27
-rw-r--r--libpod/container_internal_linux.go12
-rw-r--r--libpod/container_validate.go6
-rw-r--r--libpod/events/logfile.go4
-rw-r--r--libpod/image/prune.go5
-rw-r--r--libpod/oci_conmon_exec_linux.go124
-rw-r--r--libpod/oci_conmon_linux.go122
-rw-r--r--libpod/options.go3
-rw-r--r--libpod/runtime.go3
-rw-r--r--libpod/runtime_ctr.go14
-rw-r--r--libpod/runtime_img.go7
11 files changed, 176 insertions, 151 deletions
diff --git a/libpod/container_exec.go b/libpod/container_exec.go
index bb43287d9..8d8ed14aa 100644
--- a/libpod/container_exec.go
+++ b/libpod/container_exec.go
@@ -696,6 +696,24 @@ func (c *Container) ExecResize(sessionID string, newSize define.TerminalSize) er
return errors.Wrapf(define.ErrExecSessionStateInvalid, "cannot resize container %s exec session %s as it is not running", c.ID(), session.ID())
}
+ // The exec session may have exited since we last updated.
+ // Needed to prevent race conditions around short-running exec sessions.
+ running, err := c.ociRuntime.ExecUpdateStatus(c, session.ID())
+ if err != nil {
+ return err
+ }
+ if !running {
+ session.State = define.ExecStateStopped
+
+ if err := c.save(); err != nil {
+ logrus.Errorf("Error saving state of container %s: %v", c.ID(), err)
+ }
+
+ return errors.Wrapf(define.ErrExecSessionStateInvalid, "cannot resize container %s exec session %s as it has stopped", c.ID(), session.ID())
+ }
+
+ // Make sure the exec session is still running.
+
return c.ociRuntime.ExecAttachResize(c, sessionID, newSize)
}
@@ -720,8 +738,13 @@ func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resi
logrus.Debugf("Sending resize events to exec session %s", sessionID)
for resizeRequest := range resize {
if err := c.ExecResize(sessionID, resizeRequest); err != nil {
- // Assume the exec session went down.
- logrus.Warnf("Error resizing exec session %s: %v", sessionID, err)
+ if errors.Cause(err) == define.ErrExecSessionStateInvalid {
+ // The exec session stopped
+ // before we could resize.
+ logrus.Infof("Missed resize on exec session %s, already stopped", sessionID)
+ } else {
+ logrus.Warnf("Error resizing exec session %s: %v", sessionID, err)
+ }
return
}
}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index a136fb72d..1990ac776 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -380,8 +380,14 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
case "z":
fallthrough
case "Z":
- if err := label.Relabel(m.Source, c.MountLabel(), label.IsShared(o)); err != nil {
- return nil, err
+ if c.MountLabel() != "" {
+ if c.ProcessLabel() != "" {
+ if err := label.Relabel(m.Source, c.MountLabel(), label.IsShared(o)); err != nil {
+ return nil, err
+ }
+ } else {
+ logrus.Infof("Not relabeling volume %q in container %s as SELinux is disabled", m.Source, c.ID())
+ }
}
default:
@@ -2214,7 +2220,7 @@ func (c *Container) getOCICgroupPath() (string, error) {
}
cgroupManager := c.CgroupManager()
switch {
- case (rootless.IsRootless() && !unified) || c.config.NoCgroups:
+ case (rootless.IsRootless() && (cgroupManager == config.CgroupfsCgroupsManager || !unified)) || c.config.NoCgroups:
return "", nil
case c.config.CgroupsMode == cgroupSplit:
if c.config.CgroupParent != "" {
diff --git a/libpod/container_validate.go b/libpod/container_validate.go
index 245121a91..aae96ae85 100644
--- a/libpod/container_validate.go
+++ b/libpod/container_validate.go
@@ -126,5 +126,11 @@ func (c *Container) validate() error {
}
}
+ // If User in the OCI spec is set, require that c.config.User is set for
+ // security reasons (a lot of our code relies on c.config.User).
+ if c.config.User == "" && (c.config.Spec.Process.User.UID != 0 || c.config.Spec.Process.User.GID != 0) {
+ return errors.Wrapf(define.ErrInvalidArg, "please set User explicitly via WithUser() instead of in OCI spec directly")
+ }
+
return nil
}
diff --git a/libpod/events/logfile.go b/libpod/events/logfile.go
index 7a32ea311..0f00525e8 100644
--- a/libpod/events/logfile.go
+++ b/libpod/events/logfile.go
@@ -7,7 +7,7 @@ import (
"time"
"github.com/containers/podman/v3/pkg/util"
- "github.com/containers/storage"
+ "github.com/containers/storage/pkg/lockfile"
"github.com/pkg/errors"
)
@@ -20,7 +20,7 @@ type EventLogFile struct {
// Writes to the log file
func (e EventLogFile) Write(ee Event) error {
// We need to lock events file
- lock, err := storage.GetLockfile(e.options.LogFilePath + ".lock")
+ lock, err := lockfile.GetLockfile(e.options.LogFilePath + ".lock")
if err != nil {
return err
}
diff --git a/libpod/image/prune.go b/libpod/image/prune.go
index 12727901a..0e41fde44 100644
--- a/libpod/image/prune.go
+++ b/libpod/image/prune.go
@@ -134,10 +134,11 @@ func (ir *Runtime) PruneImages(ctx context.Context, all bool, filter []string) (
}
nameOrID := img.ID()
s, err := img.Size(ctx)
- imgSize := *s
+ imgSize := uint64(0)
if err != nil {
logrus.Warnf("Failed to collect image size for: %s, %s", nameOrID, err)
- imgSize = 0
+ } else {
+ imgSize = *s
}
if err := img.Remove(ctx, false); err != nil {
if errors.Cause(err) == storage.ErrImageUsedByContainer {
diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go
index 173edba2b..b43316951 100644
--- a/libpod/oci_conmon_exec_linux.go
+++ b/libpod/oci_conmon_exec_linux.go
@@ -2,18 +2,23 @@ package libpod
import (
"fmt"
+ "io/ioutil"
"net/http"
"os"
"os/exec"
"path/filepath"
+ "strings"
"syscall"
"time"
+ "github.com/containers/common/pkg/capabilities"
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/errorhandling"
+ "github.com/containers/podman/v3/pkg/lookup"
"github.com/containers/podman/v3/pkg/util"
"github.com/containers/podman/v3/utils"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
@@ -654,3 +659,122 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp
}
}
}
+
+// 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, options *ExecOptions, env []string, sessionID string) (*os.File, error) {
+ f, err := ioutil.TempFile(c.execBundlePath(sessionID), "exec-process-")
+ if err != nil {
+ return nil, err
+ }
+ pspec := new(spec.Process)
+ if err := JSONDeepCopy(c.config.Spec.Process, pspec); err != nil {
+ return nil, err
+ }
+ pspec.SelinuxLabel = c.config.ProcessLabel
+ pspec.Args = options.Cmd
+
+ // We need to default this to false else it will inherit terminal as true
+ // from the container.
+ pspec.Terminal = false
+ if options.Terminal {
+ pspec.Terminal = true
+ }
+ if len(env) > 0 {
+ pspec.Env = append(pspec.Env, env...)
+ }
+
+ if options.Cwd != "" {
+ pspec.Cwd = options.Cwd
+ }
+
+ var addGroups []string
+ var sgids []uint32
+
+ // if the user is empty, we should inherit the user that the container is currently running with
+ user := options.User
+ if user == "" {
+ logrus.Debugf("Set user to %s", c.config.User)
+ user = c.config.User
+ addGroups = c.config.Groups
+ }
+
+ overrides := c.getUserOverrides()
+ execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, user, overrides)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(addGroups) > 0 {
+ sgids, err = lookup.GetContainerGroups(addGroups, c.state.Mountpoint, overrides)
+ if err != nil {
+ return nil, 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
+ }
+
+ ctrSpec, err := c.specFromState()
+ if err != nil {
+ return nil, err
+ }
+
+ allCaps, err := capabilities.BoundingSet()
+ if err != nil {
+ return nil, err
+ }
+ if options.Privileged {
+ pspec.Capabilities.Bounding = allCaps
+ } else {
+ pspec.Capabilities.Bounding = ctrSpec.Process.Capabilities.Bounding
+ }
+ if execUser.Uid == 0 {
+ pspec.Capabilities.Effective = pspec.Capabilities.Bounding
+ pspec.Capabilities.Inheritable = pspec.Capabilities.Bounding
+ pspec.Capabilities.Permitted = pspec.Capabilities.Bounding
+ pspec.Capabilities.Ambient = pspec.Capabilities.Bounding
+ } else {
+ if user == c.config.User {
+ pspec.Capabilities.Effective = ctrSpec.Process.Capabilities.Effective
+ pspec.Capabilities.Inheritable = ctrSpec.Process.Capabilities.Effective
+ pspec.Capabilities.Permitted = ctrSpec.Process.Capabilities.Effective
+ pspec.Capabilities.Ambient = ctrSpec.Process.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 nil, err
+ }
+
+ if err := ioutil.WriteFile(f.Name(), processJSON, 0644); err != nil {
+ return nil, err
+ }
+ return f, nil
+}
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index 1c7089e5d..5e8ed12e7 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -22,7 +22,6 @@ import (
"text/template"
"time"
- "github.com/containers/common/pkg/capabilities"
"github.com/containers/common/pkg/config"
conmonConfig "github.com/containers/conmon/runner/config"
"github.com/containers/podman/v3/libpod/define"
@@ -30,7 +29,6 @@ import (
"github.com/containers/podman/v3/pkg/cgroups"
"github.com/containers/podman/v3/pkg/checkpoint/crutils"
"github.com/containers/podman/v3/pkg/errorhandling"
- "github.com/containers/podman/v3/pkg/lookup"
"github.com/containers/podman/v3/pkg/rootless"
"github.com/containers/podman/v3/pkg/util"
"github.com/containers/podman/v3/utils"
@@ -132,8 +130,8 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime
continue
}
foundPath = true
+ logrus.Tracef("found runtime %q", runtime.path)
runtime.path = path
- logrus.Debugf("using runtime %q", path)
break
}
@@ -1195,124 +1193,6 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co
return nil
}
-// 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, options *ExecOptions, env []string, sessionID string) (*os.File, error) {
- f, err := ioutil.TempFile(c.execBundlePath(sessionID), "exec-process-")
- if err != nil {
- return nil, err
- }
- pspec := new(spec.Process)
- if err := JSONDeepCopy(c.config.Spec.Process, pspec); err != nil {
- return nil, err
- }
- pspec.SelinuxLabel = c.config.ProcessLabel
- pspec.Args = options.Cmd
-
- // We need to default this to false else it will inherit terminal as true
- // from the container.
- pspec.Terminal = false
- if options.Terminal {
- pspec.Terminal = true
- }
- if len(env) > 0 {
- pspec.Env = append(pspec.Env, env...)
- }
-
- if options.Cwd != "" {
- pspec.Cwd = options.Cwd
- }
-
- var addGroups []string
- var sgids []uint32
-
- // if the user is empty, we should inherit the user that the container is currently running with
- user := options.User
- if user == "" {
- user = c.config.User
- addGroups = c.config.Groups
- }
-
- overrides := c.getUserOverrides()
- execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, user, overrides)
- if err != nil {
- return nil, err
- }
-
- if len(addGroups) > 0 {
- sgids, err = lookup.GetContainerGroups(addGroups, c.state.Mountpoint, overrides)
- if err != nil {
- return nil, 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
- }
-
- ctrSpec, err := c.specFromState()
- if err != nil {
- return nil, err
- }
-
- allCaps, err := capabilities.BoundingSet()
- if err != nil {
- return nil, err
- }
- if options.Privileged {
- pspec.Capabilities.Bounding = allCaps
- } else {
- pspec.Capabilities.Bounding = ctrSpec.Process.Capabilities.Bounding
- }
- if execUser.Uid == 0 {
- pspec.Capabilities.Effective = pspec.Capabilities.Bounding
- pspec.Capabilities.Inheritable = pspec.Capabilities.Bounding
- pspec.Capabilities.Permitted = pspec.Capabilities.Bounding
- pspec.Capabilities.Ambient = pspec.Capabilities.Bounding
- } else {
- if user == c.config.User {
- pspec.Capabilities.Effective = ctrSpec.Process.Capabilities.Effective
- pspec.Capabilities.Inheritable = ctrSpec.Process.Capabilities.Effective
- pspec.Capabilities.Permitted = ctrSpec.Process.Capabilities.Effective
- pspec.Capabilities.Ambient = ctrSpec.Process.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 nil, err
- }
-
- if err := ioutil.WriteFile(f.Name(), processJSON, 0644); err != nil {
- return nil, err
- }
- return f, nil
-}
-
// configureConmonEnv gets the environment values to add to conmon's exec struct
// TODO this may want to be less hardcoded/more configurable in the future
func (r *ConmonOCIRuntime) configureConmonEnv(ctr *Container, runtimeDir string) ([]string, []*os.File) {
diff --git a/libpod/options.go b/libpod/options.go
index 24e9d74f4..333a7c4a5 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -77,8 +77,7 @@ func WithStorageConfig(config storage.StoreOptions) RuntimeOption {
rt.storageConfig.GraphDriverOptions = make([]string, len(config.GraphDriverOptions))
copy(rt.storageConfig.GraphDriverOptions, config.GraphDriverOptions)
} else {
- // append new options after what is specified in the config files
- rt.storageConfig.GraphDriverOptions = append(rt.storageConfig.GraphDriverOptions, config.GraphDriverOptions...)
+ rt.storageConfig.GraphDriverOptions = config.GraphDriverOptions
}
setField = true
}
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 201482c65..136db60da 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -389,7 +389,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
// This will allow us to ship configs including optional
// runtimes that might not be installed (crun, kata).
// Only a infof so default configs don't spec errors.
- logrus.Infof("Error initializing configured OCI runtime %s: %v", name, err)
+ logrus.Debugf("configured OCI runtime %s initialization failed: %v", name, err)
continue
}
@@ -416,6 +416,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
runtime.defaultOCIRuntime = ociRuntime
}
}
+ logrus.Debugf("Using OCI runtime %q", runtime.defaultOCIRuntime.Path())
// Do we have at least one valid OCI runtime?
if len(runtime.ociRuntimes) == 0 {
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 537618b65..f9b5c5c51 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -616,20 +616,6 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
}
}
- // Delete the container.
- // Not needed in Configured and Exited states, where the container
- // doesn't exist in the runtime
- if c.state.State != define.ContainerStateConfigured &&
- c.state.State != define.ContainerStateExited {
- if err := c.delete(ctx); err != nil {
- if cleanupErr == nil {
- cleanupErr = err
- } else {
- logrus.Errorf("delete container: %v", err)
- }
- }
- }
-
// Remove the container from the state
if c.config.Pod != "" {
// If we're removing the pod, the container will be evicted
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index 13ac42e7d..3588467a5 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -9,6 +9,7 @@ import (
"net/url"
"os"
+ buildahDefine "github.com/containers/buildah/define"
"github.com/containers/buildah/imagebuildah"
"github.com/containers/image/v5/directory"
"github.com/containers/image/v5/docker/reference"
@@ -165,11 +166,9 @@ func (r *Runtime) newImageBuildCompleteEvent(idOrName string) {
}
// Build adds the runtime to the imagebuildah call
-func (r *Runtime) Build(ctx context.Context, options imagebuildah.BuildOptions, dockerfiles ...string) (string, reference.Canonical, error) {
+func (r *Runtime) Build(ctx context.Context, options buildahDefine.BuildOptions, dockerfiles ...string) (string, reference.Canonical, error) {
if options.Runtime == "" {
- // Make sure that build containers use the same runtime as Podman (see #9365).
- conf := util.DefaultContainerConfig()
- options.Runtime = conf.Engine.OCIRuntime
+ options.Runtime = r.GetOCIRuntimePath()
}
id, ref, err := imagebuildah.BuildDockerfiles(ctx, r.store, options, dockerfiles...)
// Write event for build completion