From 5875e409e2b6244daed10c1dff929ae3b69724fa Mon Sep 17 00:00:00 2001
From: Valentin Rothberg <rothberg@redhat.com>
Date: Mon, 20 Sep 2021 14:48:58 +0200
Subject: [PATCH] vendor c/psgo@v1.7.1

psgo added support for listing supplementary groups via
two new descriptors:

* `groups` for supplementary groups inside the container
* `hgroups` for the counterpart on the host

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
---
 go.mod                                        |  2 +-
 go.sum                                        |  4 +-
 test/e2e/top_test.go                          |  6 +++
 .../github.com/containers/psgo/.codespellrc   |  2 +
 .../github.com/containers/psgo/.golangci.yml  |  6 +++
 vendor/github.com/containers/psgo/.travis.yml | 19 -------
 vendor/github.com/containers/psgo/Makefile    | 40 ++++++--------
 vendor/github.com/containers/psgo/README.md   |  4 ++
 vendor/github.com/containers/psgo/go.mod      |  3 +-
 vendor/github.com/containers/psgo/go.sum      |  1 -
 .../containers/psgo/internal/host/host.go     |  2 +-
 .../containers/psgo/internal/proc/ns.go       |  2 +-
 .../containers/psgo/internal/proc/pids.go     | 31 ++++++++---
 .../containers/psgo/internal/proc/status.go   |  2 +-
 .../psgo/internal/process/process.go          |  2 +-
 vendor/github.com/containers/psgo/psgo.go     | 54 +++++++++++++++++--
 vendor/modules.txt                            |  2 +-
 17 files changed, 116 insertions(+), 66 deletions(-)
 create mode 100644 vendor/github.com/containers/psgo/.codespellrc
 create mode 100644 vendor/github.com/containers/psgo/.golangci.yml
 delete mode 100644 vendor/github.com/containers/psgo/.travis.yml

diff --git a/go.mod b/go.mod
index a919b6decc..41e30cbb32 100644
--- a/go.mod
+++ b/go.mod
@@ -16,7 +16,7 @@ require (
 	github.com/containers/conmon v2.0.20+incompatible
 	github.com/containers/image/v5 v5.16.0
 	github.com/containers/ocicrypt v1.1.2
-	github.com/containers/psgo v1.6.0
+	github.com/containers/psgo v1.7.1
 	github.com/containers/storage v1.36.0
 	github.com/coreos/go-systemd/v22 v22.3.2
 	github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
diff --git a/go.sum b/go.sum
index 264247251f..60a2c9488a 100644
--- a/go.sum
+++ b/go.sum
@@ -259,8 +259,8 @@ github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgU
 github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
 github.com/containers/ocicrypt v1.1.2 h1:Ez+GAMP/4GLix5Ywo/fL7O0nY771gsBIigiqUm1aXz0=
 github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY=
-github.com/containers/psgo v1.6.0 h1:jkl/5kndKmJ/bnSFq8in6xRDAzgW26GnNuTxoycNFvk=
-github.com/containers/psgo v1.6.0/go.mod h1:ggVhB2KQi9qGZdqSlczqN0BwcJdotmpRru87S1anRO8=
+github.com/containers/psgo v1.7.1 h1:2N6KADeFvBm1aI2iXxu6+/Xh7CCkdh8p8F3F/cpIU5I=
+github.com/containers/psgo v1.7.1/go.mod h1:mWGpFzW73qWFA+blhF6l7GuKzbrACkYgr/ajiNQR+RM=
 github.com/containers/storage v1.23.5/go.mod h1:ha26Q6ngehFNhf3AWoXldvAvwI4jFe3ETQAf/CeZPyM=
 github.com/containers/storage v1.35.0/go.mod h1:qzYhasQP2/V9D9XdO+vRwkHBhsBO0oznMLzzRDQ8s20=
 github.com/containers/storage v1.36.0 h1:OelxllCW19tnNngYuZw2ty/zLabVMG5rSs3KSwO1Lzc=
diff --git a/test/e2e/top_test.go b/test/e2e/top_test.go
index 3cf6244b6d..93c4f3f12b 100644
--- a/test/e2e/top_test.go
+++ b/test/e2e/top_test.go
@@ -73,6 +73,12 @@ var _ = Describe("Podman top", func() {
 		result.WaitWithDefaultTimeout()
 		Expect(result).Should(Exit(0))
 		Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1))
+
+		// Just a smoke test since groups may change over time.
+		result = podmanTest.Podman([]string{"container", "top", "test", "groups", "hgroups"})
+		result.WaitWithDefaultTimeout()
+		Expect(result).Should(Exit(0))
+		Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1))
 	})
 
 	It("podman top with options", func() {
diff --git a/vendor/github.com/containers/psgo/.codespellrc b/vendor/github.com/containers/psgo/.codespellrc
new file mode 100644
index 0000000000..604bc21da4
--- /dev/null
+++ b/vendor/github.com/containers/psgo/.codespellrc
@@ -0,0 +1,2 @@
+[codespell]
+skip = ./vendor,./.git
diff --git a/vendor/github.com/containers/psgo/.golangci.yml b/vendor/github.com/containers/psgo/.golangci.yml
new file mode 100644
index 0000000000..a098068fe9
--- /dev/null
+++ b/vendor/github.com/containers/psgo/.golangci.yml
@@ -0,0 +1,6 @@
+# For documentation, see https://golangci-lint.run/usage/configuration/
+
+linters:
+  enable:
+    - errorlint
+    - gofumpt
diff --git a/vendor/github.com/containers/psgo/.travis.yml b/vendor/github.com/containers/psgo/.travis.yml
deleted file mode 100644
index c07bb140bf..0000000000
--- a/vendor/github.com/containers/psgo/.travis.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-language: go
-
-sudo: required
-
-servics:
-        - docker
-
-go:
-        - tip
-
-before_install:
-        - sudo add-apt-repository ppa:duggan/bats --yes
-        - sudo apt-get update -qq
-        - sudo apt-get install -qq bats
-
-script:
-        - make validate
-        - make build
-        - make test
diff --git a/vendor/github.com/containers/psgo/Makefile b/vendor/github.com/containers/psgo/Makefile
index 831dfa31fc..fb6126e7c6 100644
--- a/vendor/github.com/containers/psgo/Makefile
+++ b/vendor/github.com/containers/psgo/Makefile
@@ -1,28 +1,25 @@
-export GO111MODULE=off
-export GOPROXY=https://proxy.golang.org
-
 SHELL= /bin/bash
 GO ?= go
 BUILD_DIR := ./bin
 BIN_DIR := /usr/local/bin
 NAME := psgo
-PROJECT := github.com/containers/psgo
 BATS_TESTS := *.bats
-GO_SRC=$(shell find . -name \*.go)
 
-GO_BUILD=$(GO) build
-# Go module support: set `-mod=vendor` to use the vendored sources
-ifeq ($(shell go help mod >/dev/null 2>&1 && echo true), true)
-	GO_BUILD=GO111MODULE=on $(GO) build -mod=vendor
+# Not all platforms support -buildmode=pie, plus it's incompatible with -race.
+ifeq ($(shell $(GO) env GOOS),linux)
+	ifeq (,$(filter $(shell $(GO) env GOARCH),mips mipsle mips64 mips64le ppc64 riscv64))
+		ifeq (,$(findstring -race,$(EXTRA_BUILD_FLAGS)))
+			GO_BUILDMODE := "-buildmode=pie"
+		endif
+	endif
 endif
-
-GOBIN ?= $(GO)/bin
+GO_BUILD := $(GO) build $(GO_BUILDMODE)
 
 all: validate build
 
 .PHONY: build
-build: $(GO_SRC)
-	 $(GO_BUILD) -buildmode=pie -o $(BUILD_DIR)/$(NAME) $(PROJECT)/sample
+build:
+	 $(GO_BUILD) $(EXTRA_BUILD_FLAGS) -o $(BUILD_DIR)/$(NAME) ./sample
 
 .PHONY: clean
 clean:
@@ -30,13 +27,13 @@ clean:
 
 .PHONY: vendor
 vendor:
-	GO111MODULE=on go mod tidy
-	GO111MODULE=on go mod vendor
-	GO111MODULE=on go mod verify
+	go mod tidy
+	go mod vendor
+	go mod verify
 
 .PHONY: validate
-validate: .install.lint
-	$(GOBIN)/golangci-lint run
+validate:
+	golangci-lint run
 
 .PHONY: test
 test: test-unit test-integration
@@ -47,17 +44,12 @@ test-integration:
 
 .PHONY: test-unit
 test-unit:
-	go test -v $(PROJECT)
-	go test -v $(PROJECT)/internal/...
+	$(GO) test -v $(EXTRA_TEST_FLAGS) ./...
 
 .PHONY: install
 install:
 	sudo install -D -m755 $(BUILD_DIR)/$(NAME) $(BIN_DIR)
 
-.PHONY: .install.lint
-.install.lint:
-	VERSION=1.24.0 GOBIN=$(GOBIN) sh ./hack/install_golangci.sh
-
 .PHONY: uninstall
 uninstall:
 	sudo rm $(BIN_DIR)/$(NAME)
diff --git a/vendor/github.com/containers/psgo/README.md b/vendor/github.com/containers/psgo/README.md
index fed42c6834..684c80a0c0 100644
--- a/vendor/github.com/containers/psgo/README.md
+++ b/vendor/github.com/containers/psgo/README.md
@@ -73,8 +73,12 @@ The ps library is compatible with all AIX format descriptors of the ps command-l
   - Set of inheritable capabilities. See capabilities(7) for more information.
 - **capprm**
   - Set of permitted capabilities. See capabilities(7) for more information.
+- **groups**
+  - Supplmentary groups inside the container.
 - **hgroup**
   - The corresponding effective group of a container process on the host.
+- **hgroups**
+  - Supplmentary groups on the host.
 - **hpid**
   - The corresponding host PID of a container process.
 - **huser**
diff --git a/vendor/github.com/containers/psgo/go.mod b/vendor/github.com/containers/psgo/go.mod
index 699874cf7f..fd19d9b484 100644
--- a/vendor/github.com/containers/psgo/go.mod
+++ b/vendor/github.com/containers/psgo/go.mod
@@ -1,10 +1,9 @@
 module github.com/containers/psgo
 
-go 1.13
+go 1.14
 
 require (
 	github.com/opencontainers/runc v1.0.2
-	github.com/sirupsen/logrus v1.8.1
 	github.com/stretchr/testify v1.7.0
 	golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2
 )
diff --git a/vendor/github.com/containers/psgo/go.sum b/vendor/github.com/containers/psgo/go.sum
index 0ba04956f0..85b0f4ff78 100644
--- a/vendor/github.com/containers/psgo/go.sum
+++ b/vendor/github.com/containers/psgo/go.sum
@@ -39,7 +39,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
 github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
diff --git a/vendor/github.com/containers/psgo/internal/host/host.go b/vendor/github.com/containers/psgo/internal/host/host.go
index 33ad67a111..3c708a2b85 100644
--- a/vendor/github.com/containers/psgo/internal/host/host.go
+++ b/vendor/github.com/containers/psgo/internal/host/host.go
@@ -54,7 +54,7 @@ func BootTime() (int64, error) {
 
 	btimeSec, err := strconv.ParseInt(btimeStr, 10, 64)
 	if err != nil {
-		return 0, fmt.Errorf("error parsing boot time from /proc/stat: %s", err)
+		return 0, fmt.Errorf("error parsing boot time from /proc/stat: %w", err)
 	}
 	bootTime = &btimeSec
 	return btimeSec, nil
diff --git a/vendor/github.com/containers/psgo/internal/proc/ns.go b/vendor/github.com/containers/psgo/internal/proc/ns.go
index 4778048f28..28ee6a2c96 100644
--- a/vendor/github.com/containers/psgo/internal/proc/ns.go
+++ b/vendor/github.com/containers/psgo/internal/proc/ns.go
@@ -59,7 +59,7 @@ func ReadMappings(path string) ([]IDMap, error) {
 	for {
 		line, _, err := buf.ReadLine()
 		if err != nil {
-			if err == io.EOF {
+			if err == io.EOF { //nolint:errorlint // False positive, see https://github.com/polyfloyd/go-errorlint/pull/12
 				return mappings, nil
 			}
 			return nil, fmt.Errorf("cannot read line from %s: %w", path, err)
diff --git a/vendor/github.com/containers/psgo/internal/proc/pids.go b/vendor/github.com/containers/psgo/internal/proc/pids.go
index 69e8befc19..2687396e15 100644
--- a/vendor/github.com/containers/psgo/internal/proc/pids.go
+++ b/vendor/github.com/containers/psgo/internal/proc/pids.go
@@ -52,7 +52,7 @@ func GetPIDs() ([]string, error) {
 	return pids, nil
 }
 
-// GetPIDsFromCgroup returns a strings slice of all pids listesd in pid's pids
+// GetPIDsFromCgroup returns a strings slice of all pids listed in pid's pids
 // cgroup.  It automatically detects if we're running in unified mode or not.
 func GetPIDsFromCgroup(pid string) ([]string, error) {
 	unified, err := cgroups.IsCgroup2UnifiedMode()
@@ -65,11 +65,12 @@ func GetPIDsFromCgroup(pid string) ([]string, error) {
 	return getPIDsFromCgroupV1(pid)
 }
 
-// getPIDsFromCgroupV1 returns a strings slice of all pids listesd in pid's pids
+// getPIDsFromCgroupV1 returns a strings slice of all pids listed in pid's pids
 // cgroup.
 func getPIDsFromCgroupV1(pid string) ([]string, error) {
 	// First, find the corresponding path to the PID cgroup.
-	f, err := os.Open(fmt.Sprintf("/proc/%s/cgroup", pid))
+	pidPath := fmt.Sprintf("/proc/%s/cgroup", pid)
+	f, err := os.Open(pidPath)
 	if err != nil {
 		return nil, err
 	}
@@ -83,7 +84,8 @@ func getPIDsFromCgroupV1(pid string) ([]string, error) {
 			continue
 		}
 		if fields[1] == "pids" {
-			cgroupPath = fmt.Sprintf("/sys/fs/cgroup/pids/%s/cgroup.procs", fields[2])
+			cgroupPath = filepath.Join(cgroups.CgroupRoot, "pids", fields[2], "cgroup.procs")
+			break
 		}
 	}
 
@@ -94,7 +96,18 @@ func getPIDsFromCgroupV1(pid string) ([]string, error) {
 	// Second, extract the PIDs inside the cgroup.
 	f, err = os.Open(cgroupPath)
 	if err != nil {
-		return nil, err
+		if os.IsNotExist(err) {
+			// OCI runtimes might mount the container cgroup at the root, breaking what it showed
+			// in /proc/$PID/cgroup and the path.
+			// Check if the PID still exists to make sure the process is still alive.
+			if _, errStat := os.Stat(pidPath); errStat == nil {
+				cgroupPath = filepath.Join(cgroups.CgroupRoot, "pids", "cgroup.procs")
+				f, err = os.Open(cgroupPath)
+			}
+		}
+		if err != nil {
+			return nil, err
+		}
 	}
 	defer f.Close()
 
@@ -107,7 +120,7 @@ func getPIDsFromCgroupV1(pid string) ([]string, error) {
 	return pids, nil
 }
 
-// getPIDsFromCgroupV2 returns a strings slice of all pids listesd in pid's pids
+// getPIDsFromCgroupV2 returns a strings slice of all pids listed in pid's pids
 // cgroup.
 func getPIDsFromCgroupV2(pid string) ([]string, error) {
 	// First, find the corresponding path to the PID cgroup.
@@ -124,8 +137,10 @@ func getPIDsFromCgroupV2(pid string) ([]string, error) {
 		if len(fields) != 3 {
 			continue
 		}
-		cgroupSlice = fields[2]
-		break
+		if fields[1] == "" {
+			cgroupSlice = fields[2]
+			break
+		}
 	}
 
 	if cgroupSlice == "" {
diff --git a/vendor/github.com/containers/psgo/internal/proc/status.go b/vendor/github.com/containers/psgo/internal/proc/status.go
index 2753915fd6..1896b5c078 100644
--- a/vendor/github.com/containers/psgo/internal/proc/status.go
+++ b/vendor/github.com/containers/psgo/internal/proc/status.go
@@ -182,7 +182,7 @@ func readStatusUserNS(pid string) ([]string, error) {
 	c := exec.Command(args[0], args[1:]...)
 	output, err := c.CombinedOutput()
 	if err != nil {
-		return nil, fmt.Errorf("error executing %q: %v", strings.Join(args, " "), err)
+		return nil, fmt.Errorf("error executing %q: %w", strings.Join(args, " "), err)
 	}
 
 	return strings.Split(string(output), "\n"), nil
diff --git a/vendor/github.com/containers/psgo/internal/process/process.go b/vendor/github.com/containers/psgo/internal/process/process.go
index 8fd49e4166..7150396109 100644
--- a/vendor/github.com/containers/psgo/internal/process/process.go
+++ b/vendor/github.com/containers/psgo/internal/process/process.go
@@ -215,7 +215,7 @@ func (p *Process) StartTime() (time.Time, error) {
 	return time.Unix(sinceBoot+bootTime, 0), nil
 }
 
-// CPUTime returns the cumlative CPU time of process p as a time.Duration.
+// CPUTime returns the cumulative CPU time of process p as a time.Duration.
 func (p *Process) CPUTime() (time.Duration, error) {
 	user, err := strconv.ParseInt(p.Stat.Utime, 10, 64)
 	if err != nil {
diff --git a/vendor/github.com/containers/psgo/psgo.go b/vendor/github.com/containers/psgo/psgo.go
index b0569fa1c7..ea893e7ca8 100644
--- a/vendor/github.com/containers/psgo/psgo.go
+++ b/vendor/github.com/containers/psgo/psgo.go
@@ -174,6 +174,11 @@ var (
 			header: "GROUP",
 			procFn: processGROUP,
 		},
+		{
+			normal: "groups",
+			header: "GROUPS",
+			procFn: processGROUPS,
+		},
 		{
 			code:   "%P",
 			normal: "ppid",
@@ -305,6 +310,12 @@ var (
 			onHost: true,
 			procFn: processHGROUP,
 		},
+		{
+			normal: "hgroups",
+			header: "HGROUPS",
+			onHost: true,
+			procFn: processHGROUPS,
+		},
 		{
 			normal: "rss",
 			header: "RSS",
@@ -620,14 +631,29 @@ func findHostProcess(p *process.Process, ctx *psContext) *process.Process {
 }
 
 // processGROUP returns the effective group ID of the process.  This will be
-// the textual group ID, if it can be optained, or a decimal representation
+// the textual group ID, if it can be obtained, or a decimal representation
 // otherwise.
 func processGROUP(p *process.Process, ctx *psContext) (string, error) {
 	return process.LookupGID(p.Status.Gids[1])
 }
 
+// processGROUPS returns the supplementary groups of the process separated by
+// comma. This will be the textual group ID, if it can be obtained, or a
+// decimal representation otherwise.
+func processGROUPS(p *process.Process, ctx *psContext) (string, error) {
+	var err error
+	groups := make([]string, len(p.Status.Groups))
+	for i, g := range p.Status.Groups {
+		groups[i], err = process.LookupGID(g)
+		if err != nil {
+			return "", err
+		}
+	}
+	return strings.Join(groups, ","), nil
+}
+
 // processRGROUP returns the real group ID of the process.  This will be
-// the textual group ID, if it can be optained, or a decimal representation
+// the textual group ID, if it can be obtained, or a decimal representation
 // otherwise.
 func processRGROUP(p *process.Process, ctx *psContext) (string, error) {
 	return process.LookupGID(p.Status.Gids[0])
@@ -639,14 +665,14 @@ func processPPID(p *process.Process, ctx *psContext) (string, error) {
 }
 
 // processUSER returns the effective user name of the process.  This will be
-// the textual user ID, if it can be optained, or a decimal representation
+// the textual user ID, if it can be obtained, or a decimal representation
 // otherwise.
 func processUSER(p *process.Process, ctx *psContext) (string, error) {
 	return process.LookupUID(p.Status.Uids[1])
 }
 
 // processRUSER returns the effective user name of the process.  This will be
-// the textual user ID, if it can be optained, or a decimal representation
+// the textual user ID, if it can be obtained, or a decimal representation
 // otherwise.
 func processRUSER(p *process.Process, ctx *psContext) (string, error) {
 	return process.LookupUID(p.Status.Uids[0])
@@ -867,6 +893,26 @@ func processHGROUP(p *process.Process, ctx *psContext) (string, error) {
 	return "?", nil
 }
 
+// processHGROUPS returns the supplementary groups of the corresponding host
+// process of the (container) or "?" if no corresponding process could be
+// found.
+func processHGROUPS(p *process.Process, ctx *psContext) (string, error) {
+	if hp := findHostProcess(p, ctx); hp != nil {
+		groups := hp.Status.Groups
+		if ctx.opts != nil && len(ctx.opts.GIDMap) > 0 {
+			var err error
+			for i, g := range groups {
+				groups[i], err = findID(g, ctx.opts.GIDMap, process.LookupGID, "/proc/sys/fs/overflowgid")
+				if err != nil {
+					return "", err
+				}
+			}
+		}
+		return strings.Join(groups, ","), nil
+	}
+	return "?", nil
+}
+
 // processRSS returns the resident set size of process p in KiB (1024-byte
 // units).
 func processRSS(p *process.Process, ctx *psContext) (string, error) {
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 324487b7c0..031f63ed19 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -191,7 +191,7 @@ github.com/containers/ocicrypt/keywrap/pkcs7
 github.com/containers/ocicrypt/spec
 github.com/containers/ocicrypt/utils
 github.com/containers/ocicrypt/utils/keyprovider
-# github.com/containers/psgo v1.6.0
+# github.com/containers/psgo v1.7.1
 github.com/containers/psgo
 github.com/containers/psgo/internal/capabilities
 github.com/containers/psgo/internal/cgroups