diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_internal_linux.go | 24 | ||||
-rw-r--r-- | libpod/events.go | 12 | ||||
-rw-r--r-- | libpod/oci_conmon_attach_common.go | 6 | ||||
-rw-r--r-- | libpod/oci_conmon_common.go | 12 | ||||
-rw-r--r-- | libpod/oci_conmon_exec_common.go | 34 | ||||
-rw-r--r-- | libpod/oci_conmon_exec_freebsd.go | 10 | ||||
-rw-r--r-- | libpod/oci_conmon_exec_linux.go | 39 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 2 |
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) |