aboutsummaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container_internal_linux.go24
-rw-r--r--libpod/events.go12
-rw-r--r--libpod/oci_conmon_attach_common.go6
-rw-r--r--libpod/oci_conmon_common.go12
-rw-r--r--libpod/oci_conmon_exec_common.go34
-rw-r--r--libpod/oci_conmon_exec_freebsd.go10
-rw-r--r--libpod/oci_conmon_exec_linux.go39
-rw-r--r--libpod/runtime_ctr.go2
8 files changed, 96 insertions, 43 deletions
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 83882ecac..9b05a2d61 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -4,6 +4,7 @@
package libpod
import (
+ "errors"
"fmt"
"os"
"path"
@@ -266,9 +267,15 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro
g.AddMount(systemdMnt)
} else {
mountOptions := []string{"bind", "rprivate"}
+ skipMount := false
var statfs unix.Statfs_t
if err := unix.Statfs("/sys/fs/cgroup/systemd", &statfs); err != nil {
+ if errors.Is(err, os.ErrNotExist) {
+ // If the mount is missing on the host, we cannot bind mount it so
+ // just skip it.
+ skipMount = true
+ }
mountOptions = append(mountOptions, "nodev", "noexec", "nosuid")
} else {
if statfs.Flags&unix.MS_NODEV == unix.MS_NODEV {
@@ -284,15 +291,16 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro
mountOptions = append(mountOptions, "ro")
}
}
-
- systemdMnt := spec.Mount{
- Destination: "/sys/fs/cgroup/systemd",
- Type: "bind",
- Source: "/sys/fs/cgroup/systemd",
- Options: mountOptions,
+ if !skipMount {
+ systemdMnt := spec.Mount{
+ Destination: "/sys/fs/cgroup/systemd",
+ Type: "bind",
+ Source: "/sys/fs/cgroup/systemd",
+ Options: mountOptions,
+ }
+ g.AddMount(systemdMnt)
+ g.AddLinuxMaskedPaths("/sys/fs/cgroup/systemd/release_agent")
}
- g.AddMount(systemdMnt)
- g.AddLinuxMaskedPaths("/sys/fs/cgroup/systemd/release_agent")
}
return nil
diff --git a/libpod/events.go b/libpod/events.go
index c9e4c9d26..60142cb60 100644
--- a/libpod/events.go
+++ b/libpod/events.go
@@ -55,6 +55,12 @@ func (c *Container) newContainerExitedEvent(exitCode int32) {
e.Image = c.config.RootfsImageName
e.Type = events.Container
e.ContainerExitCode = int(exitCode)
+
+ e.Details = events.Details{
+ ID: e.ID,
+ Attributes: c.Labels(),
+ }
+
if err := c.runtime.eventer.Write(e); err != nil {
logrus.Errorf("Unable to write container exited event: %q", err)
}
@@ -70,6 +76,12 @@ func (c *Container) newExecDiedEvent(sessionID string, exitCode int) {
e.ContainerExitCode = exitCode
e.Attributes = make(map[string]string)
e.Attributes["execID"] = sessionID
+
+ e.Details = events.Details{
+ ID: e.ID,
+ Attributes: c.Labels(),
+ }
+
if err := c.runtime.eventer.Write(e); err != nil {
logrus.Errorf("Unable to write exec died event: %q", err)
}
diff --git a/libpod/oci_conmon_attach_common.go b/libpod/oci_conmon_attach_common.go
index a9e9b2bb5..dec749837 100644
--- a/libpod/oci_conmon_attach_common.go
+++ b/libpod/oci_conmon_attach_common.go
@@ -280,20 +280,20 @@ func readStdio(conn *net.UnixConn, streams *define.AttachStreams, receiveStdoutE
var err error
select {
case err = <-receiveStdoutError:
- if err := conn.CloseWrite(); err != nil {
+ if err := socketCloseWrite(conn); err != nil {
logrus.Errorf("Failed to close stdin: %v", err)
}
return err
case err = <-stdinDone:
if err == define.ErrDetach {
- if err := conn.CloseWrite(); err != nil {
+ if err := socketCloseWrite(conn); err != nil {
logrus.Errorf("Failed to close stdin: %v", err)
}
return err
}
if err == nil {
// copy stdin is done, close it
- if connErr := conn.CloseWrite(); connErr != nil {
+ if connErr := socketCloseWrite(conn); connErr != nil {
logrus.Errorf("Unable to close conn: %v", connErr)
}
}
diff --git a/libpod/oci_conmon_common.go b/libpod/oci_conmon_common.go
index cc65e1261..87f0aa4ad 100644
--- a/libpod/oci_conmon_common.go
+++ b/libpod/oci_conmon_common.go
@@ -477,6 +477,16 @@ func (r *ConmonOCIRuntime) UnpauseContainer(ctr *Container) error {
return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, env, r.path, append(r.runtimeFlags, "resume", ctr.ID())...)
}
+// This filters out ENOTCONN errors which can happen on FreeBSD if the
+// other side of the connection is already closed.
+func socketCloseWrite(conn *net.UnixConn) error {
+ err := conn.CloseWrite()
+ if err != nil && errors.Is(err, syscall.ENOTCONN) {
+ return nil
+ }
+ return err
+}
+
// HTTPAttach performs an attach for the HTTP API.
// The caller must handle closing the HTTP connection after this returns.
// The cancel channel is not closed; it is up to the caller to do so after
@@ -689,7 +699,7 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http.
return err
}
// copy stdin is done, close it
- if connErr := conn.CloseWrite(); connErr != nil {
+ if connErr := socketCloseWrite(conn); connErr != nil {
logrus.Errorf("Unable to close conn: %v", connErr)
}
case <-cancel:
diff --git a/libpod/oci_conmon_exec_common.go b/libpod/oci_conmon_exec_common.go
index 16cd7ef9f..735dbb9c4 100644
--- a/libpod/oci_conmon_exec_common.go
+++ b/libpod/oci_conmon_exec_common.go
@@ -12,7 +12,6 @@ import (
"syscall"
"time"
- "github.com/containers/common/pkg/capabilities"
"github.com/containers/common/pkg/config"
"github.com/containers/common/pkg/resize"
cutil "github.com/containers/common/pkg/util"
@@ -386,7 +385,7 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex
finalEnv = append(finalEnv, fmt.Sprintf("%s=%s", k, v))
}
- processFile, err := prepareProcessExec(c, options, finalEnv, sessionID)
+ processFile, err := c.prepareProcessExec(options, finalEnv, sessionID)
if err != nil {
return nil, nil, err
}
@@ -654,7 +653,7 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp
return err
}
// copy stdin is done, close it
- if connErr := conn.CloseWrite(); connErr != nil {
+ if connErr := socketCloseWrite(conn); connErr != nil {
logrus.Errorf("Unable to close conn: %v", connErr)
}
case <-cancel:
@@ -665,7 +664,7 @@ 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) {
+func (c *Container) prepareProcessExec(options *ExecOptions, env []string, sessionID string) (*os.File, error) {
f, err := ioutil.TempFile(c.execBundlePath(sessionID), "exec-process-")
if err != nil {
return nil, err
@@ -745,34 +744,9 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio
pspec.User = processUser
}
- ctrSpec, err := c.specFromState()
- if err != nil {
- return nil, err
- }
-
- allCaps, err := capabilities.BoundingSet()
- if err != nil {
+ if err := c.setProcessCapabilitiesExec(options, user, execUser, pspec); err != nil {
return nil, err
}
- if options.Privileged {
- pspec.Capabilities.Bounding = allCaps
- } else {
- pspec.Capabilities.Bounding = ctrSpec.Process.Capabilities.Bounding
- }
-
- // Always unset the inheritable capabilities similarly to what the Linux kernel does
- // They are used only when using capabilities with uid != 0.
- pspec.Capabilities.Inheritable = []string{}
-
- if execUser.Uid == 0 {
- pspec.Capabilities.Effective = pspec.Capabilities.Bounding
- pspec.Capabilities.Permitted = 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 {
diff --git a/libpod/oci_conmon_exec_freebsd.go b/libpod/oci_conmon_exec_freebsd.go
new file mode 100644
index 000000000..bf30404a1
--- /dev/null
+++ b/libpod/oci_conmon_exec_freebsd.go
@@ -0,0 +1,10 @@
+package libpod
+
+import (
+ "github.com/opencontainers/runc/libcontainer/user"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+)
+
+func (c *Container) setProcessCapabilitiesExec(options *ExecOptions, user string, execUser *user.ExecUser, pspec *spec.Process) error {
+ return nil
+}
diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go
new file mode 100644
index 000000000..617e8d601
--- /dev/null
+++ b/libpod/oci_conmon_exec_linux.go
@@ -0,0 +1,39 @@
+package libpod
+
+import (
+ "github.com/containers/common/pkg/capabilities"
+ "github.com/opencontainers/runc/libcontainer/user"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+)
+
+func (c *Container) setProcessCapabilitiesExec(options *ExecOptions, user string, execUser *user.ExecUser, pspec *spec.Process) error {
+ ctrSpec, err := c.specFromState()
+ if err != nil {
+ return err
+ }
+
+ allCaps, err := capabilities.BoundingSet()
+ if err != nil {
+ return err
+ }
+ if options.Privileged {
+ pspec.Capabilities.Bounding = allCaps
+ } else {
+ pspec.Capabilities.Bounding = ctrSpec.Process.Capabilities.Bounding
+ }
+
+ // Always unset the inheritable capabilities similarly to what the Linux kernel does
+ // They are used only when using capabilities with uid != 0.
+ pspec.Capabilities.Inheritable = []string{}
+
+ if execUser.Uid == 0 {
+ pspec.Capabilities.Effective = pspec.Capabilities.Bounding
+ pspec.Capabilities.Permitted = 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
+ }
+ return nil
+}
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 1e1b7dad5..fb4f80aa6 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -798,7 +798,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
// Deallocate the container's lock
if err := c.lock.Free(); err != nil {
- if cleanupErr == nil {
+ if cleanupErr == nil && !os.IsNotExist(err) {
cleanupErr = fmt.Errorf("error freeing lock for container %s: %w", c.ID(), err)
} else {
logrus.Errorf("Free container lock: %v", err)