diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_api.go | 16 | ||||
-rw-r--r-- | libpod/container_exec.go | 10 | ||||
-rw-r--r-- | libpod/container_internal.go | 11 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 136 | ||||
-rw-r--r-- | libpod/container_log.go | 2 | ||||
-rw-r--r-- | libpod/networking_linux.go | 2 | ||||
-rw-r--r-- | libpod/oci.go | 4 | ||||
-rw-r--r-- | libpod/oci_attach_linux.go | 29 | ||||
-rw-r--r-- | libpod/oci_attach_linux_cgo.go | 11 | ||||
-rw-r--r-- | libpod/oci_attach_linux_nocgo.go | 7 | ||||
-rw-r--r-- | libpod/oci_conmon_exec_linux.go | 10 | ||||
-rw-r--r-- | libpod/oci_conmon_linux.go | 62 | ||||
-rw-r--r-- | libpod/options.go | 2 |
13 files changed, 223 insertions, 79 deletions
diff --git a/libpod/container_api.go b/libpod/container_api.go index c3e1a23d2..87ff764e3 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -703,6 +703,16 @@ type ContainerCheckpointOptions struct { // important to be able to restore a container multiple // times with '--import --name'. IgnoreStaticMAC bool + // IgnoreVolumes tells the API to not export or not to import + // the content of volumes associated with the container + IgnoreVolumes bool + // Pre Checkpoint container and leave container running + PreCheckPoint bool + // Dump container with Pre Checkpoint images + WithPrevious bool + // ImportPrevious tells the API to restore container with two + // images. One is TargetFile, the other is ImportPrevious. + ImportPrevious string } // Checkpoint checkpoints a container @@ -715,6 +725,12 @@ func (c *Container) Checkpoint(ctx context.Context, options ContainerCheckpointO } } + if options.WithPrevious { + if err := c.canWithPrevious(); err != nil { + return err + } + } + if !c.batched { c.lock.Lock() defer c.lock.Unlock() diff --git a/libpod/container_exec.go b/libpod/container_exec.go index fce26acb0..5aee847e1 100644 --- a/libpod/container_exec.go +++ b/libpod/container_exec.go @@ -8,7 +8,6 @@ import ( "strconv" "time" - "github.com/containers/common/pkg/capabilities" "github.com/containers/podman/v2/libpod/define" "github.com/containers/podman/v2/libpod/events" "github.com/containers/storage/pkg/stringid" @@ -973,20 +972,12 @@ func (c *Container) removeAllExecSessions() error { // Make an ExecOptions struct to start the OCI runtime and prepare its exec // bundle. func prepareForExec(c *Container, session *ExecSession) (*ExecOptions, error) { - // TODO: check logic here - should we set Privileged if the container is - // privileged? - var capList []string - if session.Config.Privileged || c.config.Privileged { - capList = capabilities.AllCapabilities() - } - if err := c.createExecBundle(session.ID()); err != nil { return nil, err } opts := new(ExecOptions) opts.Cmd = session.Config.Command - opts.CapAdd = capList opts.Env = session.Config.Environment opts.Terminal = session.Config.Terminal opts.Cwd = session.Config.WorkDir @@ -995,6 +986,7 @@ func prepareForExec(c *Container, session *ExecSession) (*ExecOptions, error) { opts.DetachKeys = session.Config.DetachKeys opts.ExitCommand = session.Config.ExitCommand opts.ExitCommandDelay = session.Config.ExitCommandDelay + opts.Privileged = session.Config.Privileged return opts, nil } diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 540230c26..c7548e0e5 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -134,6 +134,11 @@ func (c *Container) CheckpointPath() string { return filepath.Join(c.bundlePath(), "checkpoint") } +// PreCheckpointPath returns the path to the directory containing the pre-checkpoint-images +func (c *Container) PreCheckPointPath() string { + return filepath.Join(c.bundlePath(), "pre-checkpoint") +} + // AttachSocketPath retrieves the path of the container's attach socket func (c *Container) AttachSocketPath() (string, error) { return c.ociRuntime.AttachSocketPath(c) @@ -2023,6 +2028,12 @@ func (c *Container) checkReadyForRemoval() error { return nil } +// canWithPrevious return the stat of the preCheckPoint dir +func (c *Container) canWithPrevious() error { + _, err := os.Stat(c.PreCheckPointPath()) + return err +} + // writeJSONFile marshalls and writes the given data to a JSON file // in the bundle path func (c *Container) writeJSONFile(v interface{}, file string) error { diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index cefe12209..705086bda 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -529,6 +529,13 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { } } + availableUIDs, availableGIDs, err := rootless.GetAvailableIDMaps() + if err != nil { + return nil, err + } + g.Config.Linux.UIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.UIDMappings, availableUIDs) + g.Config.Linux.GIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.GIDMappings, availableGIDs) + // Hostname handling: // If we have a UTS namespace, set Hostname in the OCI spec. // Set the HOSTNAME environment variable unless explicitly overridden by @@ -536,6 +543,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { // set it to the host's hostname instead. hostname := c.Hostname() foundUTS := false + for _, i := range c.config.Spec.Linux.Namespaces { if i.Type == spec.UTSNamespace && i.Path == "" { foundUTS = true @@ -790,11 +798,11 @@ func (c *Container) addNamespaceContainer(g *generate.Generator, ns LinuxNS, ctr return nil } -func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error { - if (len(c.config.NamedVolumes) > 0) || (len(c.Dependencies()) > 0) { - return errors.Errorf("Cannot export checkpoints of containers with named volumes or dependencies") +func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error { + if len(c.Dependencies()) > 0 { + return errors.Errorf("Cannot export checkpoints of containers with dependencies") } - logrus.Debugf("Exporting checkpoint image of container %q to %q", c.ID(), dest) + logrus.Debugf("Exporting checkpoint image of container %q to %q", c.ID(), options.TargetFile) includeFiles := []string{ "checkpoint", @@ -804,10 +812,13 @@ func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error { "spec.dump", "network.status"} + if options.PreCheckPoint { + includeFiles[0] = "pre-checkpoint" + } // Get root file-system changes included in the checkpoint archive rootfsDiffPath := filepath.Join(c.bundlePath(), "rootfs-diff.tar") deleteFilesList := filepath.Join(c.bundlePath(), "deleted.files") - if !ignoreRootfs { + if !options.IgnoreRootfs { // To correctly track deleted files, let's go through the output of 'podman diff' tarFiles, err := c.runtime.GetDiff("", c.ID()) if err != nil { @@ -870,6 +881,47 @@ func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error { } } + // Folder containing archived volumes that will be included in the export + expVolDir := filepath.Join(c.bundlePath(), "volumes") + + // Create an archive for each volume associated with the container + if !options.IgnoreVolumes { + if err := os.MkdirAll(expVolDir, 0700); err != nil { + return errors.Wrapf(err, "error creating volumes export directory %q", expVolDir) + } + + for _, v := range c.config.NamedVolumes { + volumeTarFilePath := filepath.Join("volumes", v.Name+".tar") + volumeTarFileFullPath := filepath.Join(c.bundlePath(), volumeTarFilePath) + + volumeTarFile, err := os.Create(volumeTarFileFullPath) + if err != nil { + return errors.Wrapf(err, "error creating %q", volumeTarFileFullPath) + } + + volume, err := c.runtime.GetVolume(v.Name) + if err != nil { + return err + } + + input, err := archive.TarWithOptions(volume.MountPoint(), &archive.TarOptions{ + Compression: archive.Uncompressed, + IncludeSourceDir: true, + }) + if err != nil { + return errors.Wrapf(err, "error reading volume directory %q", v.Dest) + } + + _, err = io.Copy(volumeTarFile, input) + if err != nil { + return err + } + volumeTarFile.Close() + + includeFiles = append(includeFiles, volumeTarFilePath) + } + } + input, err := archive.TarWithOptions(c.bundlePath(), &archive.TarOptions{ Compression: archive.Gzip, IncludeSourceDir: true, @@ -880,13 +932,13 @@ func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error { return errors.Wrapf(err, "error reading checkpoint directory %q", c.ID()) } - outFile, err := os.Create(dest) + outFile, err := os.Create(options.TargetFile) if err != nil { - return errors.Wrapf(err, "error creating checkpoint export file %q", dest) + return errors.Wrapf(err, "error creating checkpoint export file %q", options.TargetFile) } defer outFile.Close() - if err := os.Chmod(dest, 0600); err != nil { + if err := os.Chmod(options.TargetFile, 0600); err != nil { return err } @@ -898,6 +950,10 @@ func (c *Container) exportCheckpoint(dest string, ignoreRootfs bool) error { os.Remove(rootfsDiffPath) os.Remove(deleteFilesList) + if !options.IgnoreVolumes { + os.RemoveAll(expVolDir) + } + return nil } @@ -962,15 +1018,24 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO defer c.newContainerEvent(events.Checkpoint) + // There is a bug from criu: https://github.com/checkpoint-restore/criu/issues/116 + // We have to change the symbolic link from absolute path to relative path + if options.WithPrevious { + os.Remove(path.Join(c.CheckpointPath(), "parent")) + if err := os.Symlink("../pre-checkpoint", path.Join(c.CheckpointPath(), "parent")); err != nil { + return err + } + } + if options.TargetFile != "" { - if err = c.exportCheckpoint(options.TargetFile, options.IgnoreRootfs); err != nil { + if err = c.exportCheckpoint(options); err != nil { return err } } logrus.Debugf("Checkpointed container %s", c.ID()) - if !options.KeepRunning { + if !options.KeepRunning && !options.PreCheckPoint { c.state.State = define.ContainerStateStopped // Cleanup Storage and Network @@ -979,7 +1044,7 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO } } - if !options.Keep { + if !options.Keep && !options.PreCheckPoint { cleanup := []string{ "dump.log", "stats-dump", @@ -1027,6 +1092,21 @@ func (c *Container) importCheckpoint(input string) error { return nil } +func (c *Container) importPreCheckpoint(input string) error { + archiveFile, err := os.Open(input) + if err != nil { + return errors.Wrap(err, "failed to open pre-checkpoint archive for import") + } + + defer archiveFile.Close() + + err = archive.Untar(archiveFile, c.bundlePath(), nil) + if err != nil { + return errors.Wrapf(err, "Unpacking of pre-checkpoint archive %s failed", input) + } + return nil +} + func (c *Container) restore(ctx context.Context, options ContainerCheckpointOptions) (retErr error) { if err := c.checkpointRestoreSupported(); err != nil { return err @@ -1036,6 +1116,12 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti return errors.Wrapf(define.ErrCtrStateInvalid, "container %s is running or paused, cannot restore", c.ID()) } + if options.ImportPrevious != "" { + if err := c.importPreCheckpoint(options.ImportPrevious); err != nil { + return err + } + } + if options.TargetFile != "" { if err := c.importCheckpoint(options.TargetFile); err != nil { return err @@ -1193,6 +1279,30 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti return err } + // When restoring from an imported archive, allow restoring the content of volumes. + // Volumes are created in setupContainer() + if options.TargetFile != "" && !options.IgnoreVolumes { + for _, v := range c.config.NamedVolumes { + volumeFilePath := filepath.Join(c.bundlePath(), "volumes", v.Name+".tar") + + volumeFile, err := os.Open(volumeFilePath) + if err != nil { + return errors.Wrapf(err, "Failed to open volume file %s", volumeFilePath) + } + defer volumeFile.Close() + + volume, err := c.runtime.GetVolume(v.Name) + if err != nil { + return errors.Wrapf(err, "Failed to retrieve volume %s", v.Name) + } + + mountPoint := volume.MountPoint() + if err := archive.UntarUncompressed(volumeFile, mountPoint, nil); err != nil { + return errors.Wrapf(err, "Failed to extract volume %s to %s", volumeFilePath, mountPoint) + } + } + } + // Before actually restarting the container, apply the root file-system changes if !options.IgnoreRootfs { rootfsDiffPath := filepath.Join(c.bundlePath(), "rootfs-diff.tar") @@ -1245,6 +1355,10 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti if err != nil { logrus.Debugf("Non-fatal: removal of checkpoint directory (%s) failed: %v", c.CheckpointPath(), err) } + err = os.RemoveAll(c.PreCheckPointPath()) + if err != nil { + logrus.Debugf("Non-fatal: removal of pre-checkpoint directory (%s) failed: %v", c.PreCheckPointPath(), err) + } cleanup := [...]string{"restore.log", "dump.log", "stats-dump", "stats-restore", "network.status", "rootfs-diff.tar", "deleted.files"} for _, del := range cleanup { file := filepath.Join(c.bundlePath(), del) diff --git a/libpod/container_log.go b/libpod/container_log.go index e58503bd3..f16e08353 100644 --- a/libpod/container_log.go +++ b/libpod/container_log.go @@ -82,7 +82,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption if nll.Partial() { partial += nll.Msg continue - } else if !nll.Partial() && len(partial) > 1 { + } else if !nll.Partial() && len(partial) > 0 { nll.Msg = partial + nll.Msg partial = "" } diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index be6867399..addf1814c 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -685,7 +685,7 @@ func (r *Runtime) setupNetNS(ctr *Container) error { return errors.Wrapf(err, "failed to generate random netns name") } - nsPath := fmt.Sprintf("/var/run/netns/cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) + nsPath := fmt.Sprintf("/run/netns/cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:]) if err := os.MkdirAll(filepath.Dir(nsPath), 0711); err != nil { return err diff --git a/libpod/oci.go b/libpod/oci.go index 157c42c38..6948e6425 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -151,8 +151,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. @@ -181,6 +179,8 @@ type ExecOptions struct { // ExitCommandDelay is a delay (in seconds) between the exec session // exiting, and the exit command being invoked. ExitCommandDelay uint + // Privileged indicates the execed process will be launched in Privileged mode + Privileged bool } // HTTPAttachStreams informs the HTTPAttach endpoint which of the container's diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go index fbc95510e..4556eba94 100644 --- a/libpod/oci_attach_linux.go +++ b/libpod/oci_attach_linux.go @@ -28,6 +28,15 @@ const ( AttachPipeStderr = 3 ) +func openUnixSocket(path string) (*net.UnixConn, error) { + fd, err := unix.Open(path, unix.O_PATH, 0) + if err != nil { + return nil, err + } + defer unix.Close(fd) + return net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: fmt.Sprintf("/proc/self/fd/%d", fd), Net: "unixpacket"}) +} + // Attach to the given container // Does not check if state is appropriate // started is only required if startContainer is true @@ -52,11 +61,10 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <- if err != nil { return err } - socketPath := buildSocketPath(attachSock) - conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"}) + conn, err := openUnixSocket(attachSock) if err != nil { - return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath) + return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock) } defer func() { if err := conn.Close(); err != nil { @@ -124,7 +132,6 @@ func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, se if err != nil { return err } - socketPath := buildSocketPath(sockPath) // 2: read from attachFd that the parent process has set up the console socket if _, err := readConmonPipeData(attachFd, ""); err != nil { @@ -132,9 +139,9 @@ func (c *Container) attachToExec(streams *define.AttachStreams, keys *string, se } // 2: then attach - conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"}) + conn, err := openUnixSocket(sockPath) if err != nil { - return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath) + return errors.Wrapf(err, "failed to connect to container's attach socket: %v", sockPath) } defer func() { if err := conn.Close(); err != nil { @@ -182,16 +189,6 @@ func registerResizeFunc(resize <-chan remotecommand.TerminalSize, bundlePath str }) } -func buildSocketPath(socketPath string) string { - maxUnixLength := unixPathLength() - if maxUnixLength < len(socketPath) { - socketPath = socketPath[0:maxUnixLength] - } - - logrus.Debug("connecting to socket ", socketPath) - return socketPath -} - func setupStdioChannels(streams *define.AttachStreams, conn *net.UnixConn, detachKeys []byte) (chan error, chan error) { receiveStdoutError := make(chan error) go func() { diff --git a/libpod/oci_attach_linux_cgo.go b/libpod/oci_attach_linux_cgo.go deleted file mode 100644 index d81243360..000000000 --- a/libpod/oci_attach_linux_cgo.go +++ /dev/null @@ -1,11 +0,0 @@ -//+build linux,cgo - -package libpod - -//#include <sys/un.h> -// extern int unix_path_length(){struct sockaddr_un addr; return sizeof(addr.sun_path) - 1;} -import "C" - -func unixPathLength() int { - return int(C.unix_path_length()) -} diff --git a/libpod/oci_attach_linux_nocgo.go b/libpod/oci_attach_linux_nocgo.go deleted file mode 100644 index a514a555d..000000000 --- a/libpod/oci_attach_linux_nocgo.go +++ /dev/null @@ -1,7 +0,0 @@ -//+build linux,!cgo - -package libpod - -func unixPathLength() int { - return 107 -} diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go index 4546acefb..dc5dd03df 100644 --- a/libpod/oci_conmon_exec_linux.go +++ b/libpod/oci_conmon_exec_linux.go @@ -2,7 +2,6 @@ package libpod import ( "fmt" - "net" "net/http" "os" "os/exec" @@ -398,10 +397,6 @@ func (r *ConmonOCIRuntime) startExec(c *Container, sessionID string, options *Ex 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") } @@ -516,7 +511,6 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp if err != nil { return err } - socketPath := buildSocketPath(sockPath) // 2: read from attachFd that the parent process has set up the console socket if _, err := readConmonPipeData(pipes.attachPipe, ""); err != nil { @@ -524,9 +518,9 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp } // 2: then attach - conn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"}) + conn, err := openUnixSocket(sockPath) if err != nil { - return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath) + return errors.Wrapf(err, "failed to connect to container's attach socket: %v", sockPath) } defer func() { if err := conn.Close(); err != nil { diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index e7cb5a802..70896cda4 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -22,6 +22,7 @@ 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/v2/libpod/define" @@ -528,13 +529,12 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http. if err != nil { return err } - socketPath := buildSocketPath(attachSock) var conn *net.UnixConn if streamAttach { - newConn, err := net.DialUnix("unixpacket", nil, &net.UnixAddr{Name: socketPath, Net: "unixpacket"}) + newConn, err := openUnixSocket(attachSock) if err != nil { - return errors.Wrapf(err, "failed to connect to container's attach socket: %v", socketPath) + return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock) } conn = newConn defer func() { @@ -543,7 +543,7 @@ func (r *ConmonOCIRuntime) HTTPAttach(ctr *Container, req *http.Request, w http. } }() - logrus.Debugf("Successfully connected to container %s attach socket %s", ctr.ID(), socketPath) + logrus.Debugf("Successfully connected to container %s attach socket %s", ctr.ID(), attachSock) } detachString := ctr.runtime.config.Engine.DetachKeys @@ -768,10 +768,14 @@ func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options Container } // imagePath is used by CRIU to store the actual checkpoint files imagePath := ctr.CheckpointPath() + if options.PreCheckPoint { + imagePath = ctr.PreCheckPointPath() + } // workPath will be used to store dump.log and stats-dump workPath := ctr.bundlePath() logrus.Debugf("Writing checkpoint to %s", imagePath) logrus.Debugf("Writing checkpoint logs to %s", workPath) + logrus.Debugf("Pre-dump the container %t", options.PreCheckPoint) args := []string{} args = append(args, r.runtimeFlags...) args = append(args, "checkpoint") @@ -785,6 +789,15 @@ func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options Container if options.TCPEstablished { args = append(args, "--tcp-established") } + if !options.PreCheckPoint && options.KeepRunning { + args = append(args, "--leave-running") + } + if options.PreCheckPoint { + args = append(args, "--pre-dump") + } + if !options.PreCheckPoint && options.WithPrevious { + args = append(args, "--parent-path", ctr.PreCheckPointPath()) + } runtimeDir, err := util.GetRuntimeDir() if err != nil { return err @@ -793,6 +806,7 @@ func (r *ConmonOCIRuntime) CheckpointContainer(ctr *Container, options Container return errors.Wrapf(err, "cannot set XDG_RUNTIME_DIR") } args = append(args, ctr.ID()) + logrus.Debugf("the args to checkpoint: %s %s", r.path, strings.Join(args, " ")) return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, args...) } @@ -1201,13 +1215,7 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio } pspec.SelinuxLabel = c.config.ProcessLabel pspec.Args = options.Cmd - for _, cap := range options.CapAdd { - pspec.Capabilities.Bounding = append(pspec.Capabilities.Bounding, cap) - pspec.Capabilities.Effective = append(pspec.Capabilities.Effective, cap) - pspec.Capabilities.Inheritable = append(pspec.Capabilities.Inheritable, cap) - pspec.Capabilities.Permitted = append(pspec.Capabilities.Permitted, cap) - pspec.Capabilities.Ambient = append(pspec.Capabilities.Ambient, cap) - } + // We need to default this to false else it will inherit terminal as true // from the container. pspec.Terminal = false @@ -1263,6 +1271,31 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio pspec.User = processUser } + ctrSpec, err := c.specFromState() + if err != nil { + return nil, err + } + + allCaps := capabilities.AllCapabilities() + 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=") { @@ -1288,7 +1321,12 @@ func prepareProcessExec(c *Container, options *ExecOptions, env []string, sessio // 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) { - env := make([]string, 0, 6) + var env []string + for _, e := range os.Environ() { + if strings.HasPrefix(e, "LC_") { + env = append(env, e) + } + } env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)) env = append(env, fmt.Sprintf("_CONTAINERS_USERNS_CONFIGURED=%s", os.Getenv("_CONTAINERS_USERNS_CONFIGURED"))) env = append(env, fmt.Sprintf("_CONTAINERS_ROOTLESS_UID=%s", os.Getenv("_CONTAINERS_ROOTLESS_UID"))) diff --git a/libpod/options.go b/libpod/options.go index 8100eee62..ef7db3235 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -306,7 +306,7 @@ func WithDefaultMountsFile(mountsFile string) RuntimeOption { // WithTmpDir sets the directory that temporary runtime files which are not // expected to survive across reboots will be stored. -// This should be located on a tmpfs mount (/tmp or /var/run for example). +// This should be located on a tmpfs mount (/tmp or /run for example). func WithTmpDir(dir string) RuntimeOption { return func(rt *Runtime) error { if rt.valid { |