diff options
-rw-r--r-- | cmd/podman/containers/ps.go | 4 | ||||
-rw-r--r-- | cmd/podman/containers/stats.go | 4 | ||||
-rw-r--r-- | libpod/container_internal.go | 35 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.c | 2 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.go | 35 | ||||
-rw-r--r-- | test/e2e/ps_test.go | 8 | ||||
-rw-r--r-- | test/system/070-build.bats | 8 |
7 files changed, 71 insertions, 25 deletions
diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go index 34fa4fab5..64271031d 100644 --- a/cmd/podman/containers/ps.go +++ b/cmd/podman/containers/ps.go @@ -307,6 +307,10 @@ func (l psReporter) Status() string { return l.State() } +func (l psReporter) RunningFor() string { + return l.CreatedHuman() +} + // Command returns the container command in string format func (l psReporter) Command() string { command := strings.Join(l.ListContainer.Command, " ") diff --git a/cmd/podman/containers/stats.go b/cmd/podman/containers/stats.go index 2b4c46647..ddb5f32ef 100644 --- a/cmd/podman/containers/stats.go +++ b/cmd/podman/containers/stats.go @@ -230,8 +230,8 @@ func outputJSON(stats []*containerStats) error { Id: j.ID(), Name: j.Name, CpuPercent: j.CPUPerc(), - MemUsage: j.MemPerc(), - MemPerc: j.MemUsage(), + MemUsage: j.MemUsage(), + MemPerc: j.MemPerc(), NetIO: j.NetIO(), BlockIO: j.BlockIO(), Pids: j.PIDS(), diff --git a/libpod/container_internal.go b/libpod/container_internal.go index a5208a0df..f3f11f945 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1534,9 +1534,6 @@ func (c *Container) chownVolume(volumeName string) error { return errors.Wrapf(err, "error retrieving named volume %s for container %s", volumeName, c.ID()) } - uid := int(c.config.Spec.Process.User.UID) - gid := int(c.config.Spec.Process.User.GID) - vol.lock.Lock() defer vol.lock.Unlock() @@ -1547,22 +1544,34 @@ func (c *Container) chownVolume(volumeName string) error { if vol.state.NeedsChown { vol.state.NeedsChown = false + + uid := int(c.config.Spec.Process.User.UID) + gid := int(c.config.Spec.Process.User.GID) + + if c.config.IDMappings.UIDMap != nil { + p := idtools.IDPair{ + UID: uid, + GID: gid, + } + mappings := idtools.NewIDMappingsFromMaps(c.config.IDMappings.UIDMap, c.config.IDMappings.GIDMap) + newPair, err := mappings.ToHost(p) + if err != nil { + return errors.Wrapf(err, "error mapping user %d:%d", uid, gid) + } + uid = newPair.UID + gid = newPair.GID + } + vol.state.UIDChowned = uid vol.state.GIDChowned = gid if err := vol.save(); err != nil { return err } - err := filepath.Walk(vol.MountPoint(), func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if err := os.Lchown(path, uid, gid); err != nil { - return err - } - return nil - }) - if err != nil { + + mountPoint := vol.MountPoint() + + if err := os.Lchown(mountPoint, uid, gid); err != nil { return err } } diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index d3e43e44d..eaf2d4551 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -860,7 +860,7 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re fprintf (stderr, "cannot read from sync pipe: %s\n", strerror (errno)); _exit (EXIT_FAILURE); } - if (b != '0') + if (ret != 1 || b != '0') _exit (EXIT_FAILURE); if (syscall_setresgid (0, 0, 0) < 0) diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index b1f200cc2..ccc8a1d94 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -97,7 +97,11 @@ func GetRootlessGID() int { return os.Getegid() } -func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap) error { +func tryMappingTool(uid bool, pid int, hostID int, mappings []idtools.IDMap) error { + var tool = "newuidmap" + if !uid { + tool = "newgidmap" + } path, err := exec.LookPath(tool) if err != nil { return errors.Wrapf(err, "cannot find %s", tool) @@ -110,6 +114,15 @@ func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap) args := []string{path, fmt.Sprintf("%d", pid)} args = appendTriplet(args, 0, hostID, 1) for _, i := range mappings { + if hostID >= i.HostID && hostID < i.HostID+i.Size { + what := "UID" + where := "/etc/subuid" + if !uid { + what = "GID" + where = "/etc/subgid" + } + return errors.Errorf("invalid configuration: the specified mapping %d:%d in %q includes the user %s", i.HostID, i.Size, where, what) + } args = appendTriplet(args, i.ContainerID+1, i.HostID, i.Size) } cmd := exec.Cmd{ @@ -175,7 +188,7 @@ func GetConfiguredMappings() ([]idtools.IDMap, []idtools.IDMap, error) { return uids, gids, nil } -func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool, int, error) { +func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ bool, _ int, retErr error) { if os.Geteuid() == 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" { if os.Getenv("_CONTAINERS_USERNS_CONFIGURED") == "init" { return false, 0, runInUser() @@ -205,7 +218,11 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool, defer errorhandling.CloseQuiet(r) defer errorhandling.CloseQuiet(w) defer func() { - if _, err := w.Write([]byte("0")); err != nil { + toWrite := []byte("0") + if retErr != nil { + toWrite = []byte("1") + } + if _, err := w.Write(toWrite); err != nil { logrus.Errorf("failed to write byte 0: %q", err) } }() @@ -223,7 +240,11 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool, uidsMapped := false if uids != nil { - err := tryMappingTool("newuidmap", pid, os.Geteuid(), uids) + err := tryMappingTool(true, pid, os.Geteuid(), uids) + // If some mappings were specified, do not ignore the error + if err != nil && len(uids) > 0 { + return false, -1, err + } uidsMapped = err == nil } if !uidsMapped { @@ -245,7 +266,11 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool, gidsMapped := false if gids != nil { - err := tryMappingTool("newgidmap", pid, os.Getegid(), gids) + err := tryMappingTool(false, pid, os.Getegid(), gids) + // If some mappings were specified, do not ignore the error + if err != nil && len(gids) > 0 { + return false, -1, err + } gidsMapped = err == nil } if !gidsMapped { diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go index 281968fcd..f10ef5c99 100644 --- a/test/e2e/ps_test.go +++ b/test/e2e/ps_test.go @@ -476,5 +476,13 @@ var _ = Describe("Podman ps", func() { session.WaitWithDefaultTimeout() Expect(session.OutputToString()).To(ContainSubstring("echo very long cr...")) }) + It("podman ps --format {{RunningFor}}", func() { + _, ec, _ := podmanTest.RunLsContainer("") + Expect(ec).To(Equal(0)) + result := podmanTest.Podman([]string{"ps", "-a", "--format", "{{.RunningFor}}"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(result.OutputToString()).To(ContainSubstring("ago")) + }) }) diff --git a/test/system/070-build.bats b/test/system/070-build.bats index 627b9caa6..a69d32a2f 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -143,7 +143,7 @@ RUN mkdir -p /a/b/c RUN ln -s /no/such/nonesuch /a/b/c/badsymlink RUN ln -s /bin/mydefaultcmd /a/b/c/goodsymlink RUN touch /a/b/c/myfile -RUN chown -h 1:2 /a/b/c/badsymlink /a/b/c/goodsymlink /a/b/c/myfile +RUN chown -h 1:2 /a/b/c/badsymlink /a/b/c/goodsymlink && chown -h 4:5 /a/b/c/myfile VOLUME /a/b/c # Test for environment passing and override @@ -216,18 +216,18 @@ Labels.$label_name | $label_value # be they dangling or valid, would barf with # Error: chown <mountpath>/_data/symlink: ENOENT run_podman run --rm build_test stat -c'%u:%g:%N' /a/b/c/badsymlink - is "$output" "0:0:'/a/b/c/badsymlink' -> '/no/such/nonesuch'" \ + is "$output" "1:2:'/a/b/c/badsymlink' -> '/no/such/nonesuch'" \ "bad symlink to nonexistent file is chowned and preserved" run_podman run --rm build_test stat -c'%u:%g:%N' /a/b/c/goodsymlink - is "$output" "0:0:'/a/b/c/goodsymlink' -> '/bin/mydefaultcmd'" \ + is "$output" "1:2:'/a/b/c/goodsymlink' -> '/bin/mydefaultcmd'" \ "good symlink to existing file is chowned and preserved" run_podman run --rm build_test stat -c'%u:%g' /bin/mydefaultcmd is "$output" "2:3" "target of symlink is not chowned" run_podman run --rm build_test stat -c'%u:%g:%N' /a/b/c/myfile - is "$output" "0:0:/a/b/c/myfile" "file in volume is chowned to root" + is "$output" "4:5:/a/b/c/myfile" "file in volume is chowned" # Clean up run_podman rmi -f build_test |