summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container_exec.go2
-rw-r--r--libpod/container_internal.go10
-rw-r--r--libpod/define/errors.go4
-rw-r--r--libpod/define/fileinfo.go2
-rw-r--r--libpod/image/image.go3
-rw-r--r--libpod/image/utils.go2
-rw-r--r--libpod/oci.go4
-rw-r--r--libpod/oci_conmon_exec_linux.go13
-rw-r--r--libpod/oci_conmon_linux.go13
-rw-r--r--libpod/oci_missing.go5
-rw-r--r--libpod/runtime.go125
-rw-r--r--libpod/runtime_img.go3
-rw-r--r--libpod/shutdown/handler.go2
13 files changed, 144 insertions, 44 deletions
diff --git a/libpod/container_exec.go b/libpod/container_exec.go
index 8d8ed14aa..c359f1e5d 100644
--- a/libpod/container_exec.go
+++ b/libpod/container_exec.go
@@ -773,7 +773,7 @@ func (c *Container) cleanupExecBundle(sessionID string) error {
return err
}
- return c.ociRuntime.ExecContainerCleanup(c, sessionID)
+ return nil
}
// the path to a containers exec session bundle
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index a53027ab2..80c00a622 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -685,7 +685,11 @@ func (c *Container) removeIPv4Allocations() error {
// This is necessary for restarting containers
func (c *Container) removeConmonFiles() error {
// Files are allowed to not exist, so ignore ENOENT
- attachFile := filepath.Join(c.bundlePath(), "attach")
+ attachFile, err := c.AttachSocketPath()
+ if err != nil {
+ return errors.Wrapf(err, "failed to get attach socket path for container %s", c.ID())
+ }
+
if err := os.Remove(attachFile); err != nil && !os.IsNotExist(err) {
return errors.Wrapf(err, "error removing container %s attach file", c.ID())
}
@@ -1309,7 +1313,7 @@ func (c *Container) stop(timeout uint) error {
}
// We have to check stopErr *after* we lock again - otherwise, we have a
- // change of panicing on a double-unlock. Ref: GH Issue 9615
+ // change of panicking on a double-unlock. Ref: GH Issue 9615
if stopErr != nil {
return stopErr
}
@@ -1672,7 +1676,7 @@ func (c *Container) chownVolume(volumeName string) error {
// TODO: For now, I've disabled chowning volumes owned by non-Podman
// drivers. This may be safe, but it's really going to be a case-by-case
- // thing, I think - safest to leave disabled now and reenable later if
+ // thing, I think - safest to leave disabled now and re-enable later if
// there is a demand.
if vol.state.NeedsChown && !vol.UsesVolumeDriver() {
vol.state.NeedsChown = false
diff --git a/libpod/define/errors.go b/libpod/define/errors.go
index e19ac6a27..8d943099b 100644
--- a/libpod/define/errors.go
+++ b/libpod/define/errors.go
@@ -206,4 +206,8 @@ var (
// ErrCanceled indicates that an operation has been cancelled by a user.
// Useful for potentially long running tasks.
ErrCanceled = errors.New("cancelled by user")
+
+ // ErrConmonVersionFormat is used when the expected versio-format of conmon
+ // has changed.
+ ErrConmonVersionFormat = "conmon version changed format"
)
diff --git a/libpod/define/fileinfo.go b/libpod/define/fileinfo.go
index 2c7b6fe99..eec99e300 100644
--- a/libpod/define/fileinfo.go
+++ b/libpod/define/fileinfo.go
@@ -5,7 +5,7 @@ import (
"time"
)
-// FileInfo describes the attributes of a file or diretory.
+// FileInfo describes the attributes of a file or directory.
type FileInfo struct {
Name string `json:"name"`
Size int64 `json:"size"`
diff --git a/libpod/image/image.go b/libpod/image/image.go
index 12dc22360..3c9fb3a37 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -617,7 +617,8 @@ func (i *Image) TopLayer() string {
func (i *Image) Remove(ctx context.Context, force bool) error {
parent, err := i.GetParent(ctx)
if err != nil {
- return err
+ logrus.Warnf("error determining parent of image: %v, ignoring the error", err)
+ parent = nil
}
if _, err := i.imageruntime.store.DeleteImage(i.ID(), true); err != nil {
return err
diff --git a/libpod/image/utils.go b/libpod/image/utils.go
index 0b4264112..dfe35c017 100644
--- a/libpod/image/utils.go
+++ b/libpod/image/utils.go
@@ -50,7 +50,7 @@ func findImageInRepotags(search imageParts, images []*Image) (*storage.Image, er
// If more then one candidate and the candidates all have same name
// and only one is read/write return it.
- // Othewise return error with the list of candidates
+ // Otherwise return error with the list of candidates
if len(candidates) > 1 {
var (
rwImage *Image
diff --git a/libpod/oci.go b/libpod/oci.go
index f2053f1b5..1f2c7dd71 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -94,10 +94,6 @@ type OCIRuntime interface {
// ExecUpdateStatus checks the status of a given exec session.
// Returns true if the session is still running, or false if it exited.
ExecUpdateStatus(ctr *Container, sessionID string) (bool, error)
- // ExecContainerCleanup cleans up after an exec session exits.
- // It removes any files left by the exec session that are no longer
- // needed, including the attach socket.
- ExecContainerCleanup(ctr *Container, sessionID string) error
// CheckpointContainer checkpoints the given container.
// Some OCI runtimes may not support this - if SupportsCheckpoint()
diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go
index b43316951..76338b86c 100644
--- a/libpod/oci_conmon_exec_linux.go
+++ b/libpod/oci_conmon_exec_linux.go
@@ -284,17 +284,6 @@ func (r *ConmonOCIRuntime) ExecUpdateStatus(ctr *Container, sessionID string) (b
return true, nil
}
-// ExecContainerCleanup cleans up files created when a command is run via
-// ExecContainer. This includes the attach socket for the exec session.
-func (r *ConmonOCIRuntime) ExecContainerCleanup(ctr *Container, sessionID string) error {
- // Clean up the sockets dir. Issue #3962
- // Also ignore if it doesn't exist for some reason; hence the conditional return below
- if err := os.RemoveAll(filepath.Join(r.socketsDir, sessionID)); err != nil && !os.IsNotExist(err) {
- return err
- }
- return nil
-}
-
// ExecAttachSocketPath is the path to a container's exec session attach socket.
func (r *ConmonOCIRuntime) ExecAttachSocketPath(ctr *Container, sessionID string) (string, error) {
// We don't even use container, so don't validity check it
@@ -302,7 +291,7 @@ func (r *ConmonOCIRuntime) ExecAttachSocketPath(ctr *Container, sessionID string
return "", errors.Wrapf(define.ErrInvalidArg, "must provide a valid session ID to get attach socket path")
}
- return filepath.Join(r.socketsDir, sessionID, "attach"), nil
+ return filepath.Join(ctr.execBundlePath(sessionID), "attach"), nil
}
// This contains pipes used by the exec API.
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index dbe91c232..c1acec977 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -59,7 +59,6 @@ type ConmonOCIRuntime struct {
conmonEnv []string
tmpDir string
exitsDir string
- socketsDir string
logSizeMax int64
noPivot bool
reservePorts bool
@@ -149,7 +148,6 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime
}
runtime.exitsDir = filepath.Join(runtime.tmpDir, "exits")
- runtime.socketsDir = filepath.Join(runtime.tmpDir, "socket")
// Create the exit files and attach sockets directories
if err := os.MkdirAll(runtime.exitsDir, 0750); err != nil {
@@ -158,13 +156,6 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime
return nil, errors.Wrapf(err, "error creating OCI runtime exit files directory")
}
}
- if err := os.MkdirAll(runtime.socketsDir, 0750); err != nil {
- // The directory is allowed to exist
- if !os.IsExist(err) {
- return nil, errors.Wrap(err, "error creating OCI runtime attach sockets directory")
- }
- }
-
return runtime, nil
}
@@ -865,7 +856,7 @@ func (r *ConmonOCIRuntime) AttachSocketPath(ctr *Container) (string, error) {
return "", errors.Wrapf(define.ErrInvalidArg, "must provide a valid container to get attach socket path")
}
- return filepath.Join(r.socketsDir, ctr.ID(), "attach"), nil
+ return filepath.Join(ctr.bundlePath(), "attach"), nil
}
// ExitFilePath is the path to a container's exit file.
@@ -1240,7 +1231,7 @@ func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, p
"-p", pidPath,
"-n", ctr.Name(),
"--exit-dir", exitDir,
- "--socket-dir-path", r.socketsDir,
+ "--full-attach",
}
if len(r.runtimeFlags) > 0 {
rFlags := []string{}
diff --git a/libpod/oci_missing.go b/libpod/oci_missing.go
index eb8cdebad..10526f368 100644
--- a/libpod/oci_missing.go
+++ b/libpod/oci_missing.go
@@ -151,11 +151,6 @@ func (r *MissingRuntime) ExecUpdateStatus(ctr *Container, sessionID string) (boo
return false, r.printError()
}
-// ExecContainerCleanup is not available as the runtime is missing
-func (r *MissingRuntime) ExecContainerCleanup(ctr *Container, sessionID string) error {
- return r.printError()
-}
-
// CheckpointContainer is not available as the runtime is missing
func (r *MissingRuntime) CheckpointContainer(ctr *Container, options ContainerCheckpointOptions) error {
return r.printError()
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 98ca2d5a4..3518ed25a 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -2,10 +2,14 @@ package libpod
import (
"bufio"
+ "bytes"
"context"
"fmt"
"os"
+ "os/exec"
"path/filepath"
+ "regexp"
+ "strconv"
"strings"
"sync"
"syscall"
@@ -25,6 +29,7 @@ import (
"github.com/containers/podman/v3/pkg/rootless"
"github.com/containers/podman/v3/pkg/util"
"github.com/containers/storage"
+ "github.com/containers/storage/pkg/unshare"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/docker/docker/pkg/namesgenerator"
spec "github.com/opencontainers/runtime-spec/specs-go"
@@ -32,6 +37,17 @@ import (
"github.com/sirupsen/logrus"
)
+const (
+ // conmonMinMajorVersion is the major version required for conmon.
+ conmonMinMajorVersion = 2
+
+ // conmonMinMinorVersion is the minor version required for conmon.
+ conmonMinMinorVersion = 0
+
+ // conmonMinPatchVersion is the sub-minor version required for conmon.
+ conmonMinPatchVersion = 24
+)
+
// A RuntimeOption is a functional option which alters the Runtime created by
// NewRuntime
type RuntimeOption func(*Runtime) error
@@ -260,7 +276,7 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) {
// Sets up containers/storage, state store, OCI runtime
func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
// Find a working conmon binary
- cPath, err := runtime.config.FindConmon()
+ cPath, err := findConmon(runtime.config.Engine.ConmonPath)
if err != nil {
return err
}
@@ -323,9 +339,16 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
}
logrus.Debugf("Set libpod namespace to %q", runtime.config.Engine.Namespace)
+ hasCapSysAdmin, err := unshare.HasCapSysAdmin()
+ if err != nil {
+ return err
+ }
+
+ needsUserns := !hasCapSysAdmin
+
// Set up containers/storage
var store storage.Store
- if os.Geteuid() != 0 {
+ if needsUserns {
logrus.Debug("Not configuring container store")
} else if runtime.noStore {
logrus.Debug("No store required. Not opening container store.")
@@ -465,7 +488,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
// If we need to refresh, then it is safe to assume there are
// no containers running. Create immediately a namespace, as
// we will need to access the storage.
- if os.Geteuid() != 0 {
+ if needsUserns {
aliveLock.Unlock() // Unlock to avoid deadlock as BecomeRootInUserNS will reexec.
pausePid, err := util.GetRootlessPauseProcessPidPathGivenDir(runtime.config.Engine.TmpDir)
if err != nil {
@@ -532,6 +555,102 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
return nil
}
+// findConmon iterates over conmonPaths and returns the path
+// to the first conmon binary with a new enough version. If none is found,
+// we try to do a path lookup of "conmon".
+func findConmon(conmonPaths []string) (string, error) {
+ foundOutdatedConmon := false
+ for _, path := range conmonPaths {
+ stat, err := os.Stat(path)
+ if err != nil {
+ continue
+ }
+ if stat.IsDir() {
+ continue
+ }
+ if err := probeConmon(path); err != nil {
+ logrus.Warnf("Conmon at %s invalid: %v", path, err)
+ foundOutdatedConmon = true
+ continue
+ }
+ logrus.Debugf("Using conmon: %q", path)
+ return path, nil
+ }
+
+ // Search the $PATH as last fallback
+ if path, err := exec.LookPath("conmon"); err == nil {
+ if err := probeConmon(path); err != nil {
+ logrus.Warnf("Conmon at %s is invalid: %v", path, err)
+ foundOutdatedConmon = true
+ } else {
+ logrus.Debugf("Using conmon from $PATH: %q", path)
+ return path, nil
+ }
+ }
+
+ if foundOutdatedConmon {
+ return "", errors.Wrapf(define.ErrConmonOutdated,
+ "please update to v%d.%d.%d or later",
+ conmonMinMajorVersion, conmonMinMinorVersion, conmonMinPatchVersion)
+ }
+
+ return "", errors.Wrapf(define.ErrInvalidArg,
+ "could not find a working conmon binary (configured options: %v)",
+ conmonPaths)
+}
+
+// probeConmon calls conmon --version and verifies it is a new enough version for
+// the runtime expectations the container engine currently has.
+func probeConmon(conmonBinary string) error {
+ cmd := exec.Command(conmonBinary, "--version")
+ var out bytes.Buffer
+ cmd.Stdout = &out
+ err := cmd.Run()
+ if err != nil {
+ return err
+ }
+ r := regexp.MustCompile(`^conmon version (?P<Major>\d+).(?P<Minor>\d+).(?P<Patch>\d+)`)
+
+ matches := r.FindStringSubmatch(out.String())
+ if len(matches) != 4 {
+ return errors.Wrap(err, define.ErrConmonVersionFormat)
+ }
+ major, err := strconv.Atoi(matches[1])
+ if err != nil {
+ return errors.Wrap(err, define.ErrConmonVersionFormat)
+ }
+ if major < conmonMinMajorVersion {
+ return define.ErrConmonOutdated
+ }
+ if major > conmonMinMajorVersion {
+ return nil
+ }
+
+ minor, err := strconv.Atoi(matches[2])
+ if err != nil {
+ return errors.Wrap(err, define.ErrConmonVersionFormat)
+ }
+ if minor < conmonMinMinorVersion {
+ return define.ErrConmonOutdated
+ }
+ if minor > conmonMinMinorVersion {
+ return nil
+ }
+
+ patch, err := strconv.Atoi(matches[3])
+ if err != nil {
+ return errors.Wrap(err, define.ErrConmonVersionFormat)
+ }
+ if patch < conmonMinPatchVersion {
+ return define.ErrConmonOutdated
+ }
+ if patch > conmonMinPatchVersion {
+ return nil
+ }
+
+ return nil
+}
+
// TmpDir gets the current Libpod temporary files directory.
func (r *Runtime) TmpDir() (string, error) {
if !r.valid {
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index 3588467a5..2b101c01f 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -66,7 +66,8 @@ func (r *Runtime) RemoveImage(ctx context.Context, img *image.Image, force bool)
hasChildren, err := img.IsParent(ctx)
if err != nil {
- return nil, err
+ logrus.Warnf("error determining if an image is a parent: %v, ignoring the error", err)
+ hasChildren = false
}
if (len(img.Names()) > 1 && !img.InputIsID()) || hasChildren {
diff --git a/libpod/shutdown/handler.go b/libpod/shutdown/handler.go
index ac1d33910..848b6729a 100644
--- a/libpod/shutdown/handler.go
+++ b/libpod/shutdown/handler.go
@@ -18,7 +18,7 @@ var (
stopped bool
sigChan chan os.Signal
cancelChan chan bool
- // Syncronize accesses to the map
+ // Synchronize accesses to the map
handlerLock sync.Mutex
// Definitions of all on-shutdown handlers
handlers map[string]func(os.Signal) error