summaryrefslogtreecommitdiff
path: root/vendor
diff options
context:
space:
mode:
Diffstat (limited to 'vendor')
-rw-r--r--vendor/github.com/containers/psgo/README.md2
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/ns.go9
-rw-r--r--vendor/github.com/containers/psgo/internal/proc/status.go41
-rw-r--r--vendor/github.com/containers/psgo/internal/process/process.go15
-rw-r--r--vendor/github.com/containers/psgo/internal/types/types.go8
-rw-r--r--vendor/github.com/containers/psgo/psgo.go54
6 files changed, 107 insertions, 22 deletions
diff --git a/vendor/github.com/containers/psgo/README.md b/vendor/github.com/containers/psgo/README.md
index 7b779b539..6b0f1dab3 100644
--- a/vendor/github.com/containers/psgo/README.md
+++ b/vendor/github.com/containers/psgo/README.md
@@ -46,6 +46,8 @@ root 1 0 0.000 17.249905587s ? 0s sleep
### Format descriptors
The ps library is compatible with all AIX format descriptors of the ps command-line utility (see `man 1 ps` for details) but it also supports some additional descriptors that can be useful when seeking specific process-related information.
+- **capamb**
+ - Set of ambient capabilities. See capabilities(7) for more information.
- **capbnd**
- Set of bounding capabilities. See capabilities(7) for more information.
- **capeff**
diff --git a/vendor/github.com/containers/psgo/internal/proc/ns.go b/vendor/github.com/containers/psgo/internal/proc/ns.go
index 61b4b2b58..fbfbd4894 100644
--- a/vendor/github.com/containers/psgo/internal/proc/ns.go
+++ b/vendor/github.com/containers/psgo/internal/proc/ns.go
@@ -13,3 +13,12 @@ func ParsePIDNamespace(pid string) (string, error) {
}
return pidNS, nil
}
+
+// ParseUserNamespace returns the content of /proc/$pid/ns/user.
+func ParseUserNamespace(pid string) (string, error) {
+ userNS, err := os.Readlink(fmt.Sprintf("/proc/%s/ns/user", pid))
+ if err != nil {
+ return "", err
+ }
+ return userNS, nil
+}
diff --git a/vendor/github.com/containers/psgo/internal/proc/status.go b/vendor/github.com/containers/psgo/internal/proc/status.go
index b8e06dd6b..364d9e9a2 100644
--- a/vendor/github.com/containers/psgo/internal/proc/status.go
+++ b/vendor/github.com/containers/psgo/internal/proc/status.go
@@ -4,8 +4,10 @@ import (
"bufio"
"fmt"
"os"
+ "os/exec"
"strings"
+ "github.com/containers/psgo/internal/types"
"github.com/pkg/errors"
)
@@ -160,8 +162,24 @@ type Status struct {
NonvoluntaryCtxtSwitches string
}
-// readStatus is used for mocking in unit tests.
-var readStatus = func(path string) ([]string, error) {
+// readStatusUserNS joins the user namespace of pid and returns the content of
+// /proc/pid/status as a string slice.
+func readStatusUserNS(pid string) ([]string, error) {
+ path := fmt.Sprintf("/proc/%s/status", pid)
+ args := []string{"nsenter", "-U", "-t", pid, "cat", path}
+
+ 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 strings.Split(string(output), "\n"), nil
+}
+
+// readStatusDefault returns the content of /proc/pid/status as a string slice.
+func readStatusDefault(pid string) ([]string, error) {
+ path := fmt.Sprintf("/proc/%s/status", pid)
f, err := os.Open(path)
if err != nil {
return nil, err
@@ -175,15 +193,26 @@ var readStatus = func(path string) ([]string, error) {
}
// ParseStatus parses the /proc/$pid/status file and returns a *Status.
-func ParseStatus(pid string) (*Status, error) {
- path := fmt.Sprintf("/proc/%s/status", pid)
- lines, err := readStatus(path)
+func ParseStatus(ctx *types.PsContext, pid string) (*Status, error) {
+ var lines []string
+ var err error
+
+ if ctx.JoinUserNS {
+ lines, err = readStatusUserNS(pid)
+ } else {
+ lines, err = readStatusDefault(pid)
+ }
+
if err != nil {
return nil, err
}
+ return parseStatus(pid, lines)
+}
+// parseStatus extracts data from lines and returns a *Status.
+func parseStatus(pid string, lines []string) (*Status, error) {
s := Status{}
- errUnexpectedInput := errors.New(fmt.Sprintf("unexpected input from %s", path))
+ errUnexpectedInput := fmt.Errorf("unexpected input from /proc/%s/status", pid)
for _, line := range lines {
fields := strings.Fields(line)
if len(fields) < 2 {
diff --git a/vendor/github.com/containers/psgo/internal/process/process.go b/vendor/github.com/containers/psgo/internal/process/process.go
index b1ea076b5..6a8dfb0c0 100644
--- a/vendor/github.com/containers/psgo/internal/process/process.go
+++ b/vendor/github.com/containers/psgo/internal/process/process.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/psgo/internal/host"
"github.com/containers/psgo/internal/proc"
+ "github.com/containers/psgo/internal/types"
"github.com/opencontainers/runc/libcontainer/user"
"github.com/pkg/errors"
)
@@ -61,13 +62,13 @@ func LookupUID(uid string) (string, error) {
// New returns a new Process with the specified pid and parses the relevant
// data from /proc and /dev.
-func New(pid string) (*Process, error) {
+func New(ctx *types.PsContext, pid string) (*Process, error) {
p := Process{Pid: pid}
if err := p.parseStat(); err != nil {
return nil, err
}
- if err := p.parseStatus(); err != nil {
+ if err := p.parseStatus(ctx); err != nil {
return nil, err
}
if err := p.parseCmdLine(); err != nil {
@@ -88,10 +89,10 @@ func New(pid string) (*Process, error) {
}
// FromPIDs creates a new Process for each pid.
-func FromPIDs(pids []string) ([]*Process, error) {
+func FromPIDs(ctx *types.PsContext, pids []string) ([]*Process, error) {
processes := []*Process{}
for _, pid := range pids {
- p, err := New(pid)
+ p, err := New(ctx, pid)
if err != nil {
if os.IsNotExist(err) {
// proc parsing is racy
@@ -116,8 +117,8 @@ func (p *Process) parseStat() error {
}
// parseStatus parses /proc/$pid/status.
-func (p *Process) parseStatus() error {
- s, err := proc.ParseStatus(p.Pid)
+func (p *Process) parseStatus(ctx *types.PsContext) error {
+ s, err := proc.ParseStatus(ctx, p.Pid)
if err != nil {
return err
}
@@ -135,7 +136,7 @@ func (p *Process) parseCmdLine() error {
return nil
}
-// parsePIDNamespace parses all host-related data fields.
+// parsePIDNamespace sets the PID namespace.
func (p *Process) parsePIDNamespace() error {
pidNS, err := proc.ParsePIDNamespace(p.Pid)
if err != nil {
diff --git a/vendor/github.com/containers/psgo/internal/types/types.go b/vendor/github.com/containers/psgo/internal/types/types.go
new file mode 100644
index 000000000..9069e8000
--- /dev/null
+++ b/vendor/github.com/containers/psgo/internal/types/types.go
@@ -0,0 +1,8 @@
+package types
+
+// PsContext controls some internals of the psgo library.
+type PsContext struct {
+ // JoinUserNS will force /proc and /dev parsing from within each PIDs
+ // user namespace.
+ JoinUserNS bool
+}
diff --git a/vendor/github.com/containers/psgo/psgo.go b/vendor/github.com/containers/psgo/psgo.go
index e52089b3c..2ea9a322b 100644
--- a/vendor/github.com/containers/psgo/psgo.go
+++ b/vendor/github.com/containers/psgo/psgo.go
@@ -25,6 +25,7 @@ import (
"github.com/containers/psgo/internal/dev"
"github.com/containers/psgo/internal/proc"
"github.com/containers/psgo/internal/process"
+ "github.com/containers/psgo/internal/types"
"github.com/pkg/errors"
"golang.org/x/sys/unix"
)
@@ -183,23 +184,28 @@ var (
procFn: processVSZ,
},
{
+ normal: "capamb",
+ header: "AMBIENT CAPS",
+ procFn: processCAPAMB,
+ },
+ {
normal: "capinh",
- header: "CAPABILITIES",
+ header: "INHERITED CAPS",
procFn: processCAPINH,
},
{
normal: "capprm",
- header: "CAPABILITIES",
+ header: "PERMITTED CAPS",
procFn: processCAPPRM,
},
{
normal: "capeff",
- header: "CAPABILITIES",
+ header: "EFFECTIVE CAPS",
procFn: processCAPEFF,
},
{
normal: "capbnd",
- header: "CAPABILITIES",
+ header: "BOUNDING CAPS",
procFn: processCAPBND,
},
{
@@ -276,6 +282,19 @@ func JoinNamespaceAndProcessInfo(pid string, descriptors []string) ([][]string,
defer wg.Done()
runtime.LockOSThread()
+ // extract user namespaces prior to joining the mount namespace
+ currentUserNs, err := proc.ParseUserNamespace("self")
+ if err != nil {
+ dataErr = errors.Wrapf(err, "error determining user namespace")
+ return
+ }
+
+ pidUserNs, err := proc.ParseUserNamespace(pid)
+ if err != nil {
+ dataErr = errors.Wrapf(err, "error determining user namespace of PID %s", pid)
+ }
+
+ // join the mount namespace of pid
fd, err := os.Open(fmt.Sprintf("/proc/%s/ns/mnt", pid))
if err != nil {
dataErr = err
@@ -290,12 +309,19 @@ func JoinNamespaceAndProcessInfo(pid string, descriptors []string) ([][]string,
}
unix.Setns(int(fd.Fd()), unix.CLONE_NEWNS)
+ // extract all pids mentioned in pid's mount namespace
pids, err := proc.GetPIDs()
if err != nil {
dataErr = err
return
}
- processes, err := process.FromPIDs(pids)
+
+ ctx := types.PsContext{
+ // join the user NS if the pid's user NS is different
+ // to the caller's user NS.
+ JoinUserNS: currentUserNs != pidUserNs,
+ }
+ processes, err := process.FromPIDs(&ctx, pids)
if err != nil {
dataErr = err
return
@@ -324,7 +350,9 @@ func ProcessInfo(descriptors []string) ([][]string, error) {
if err != nil {
return nil, err
}
- processes, err := process.FromPIDs(pids)
+
+ ctx := types.PsContext{JoinUserNS: false}
+ processes, err := process.FromPIDs(&ctx, pids)
if err != nil {
return nil, err
}
@@ -340,7 +368,8 @@ func setHostProcesses(pid string) error {
return err
}
- processes, err := process.FromPIDs(pids)
+ ctx := types.PsContext{JoinUserNS: false}
+ processes, err := process.FromPIDs(&ctx, pids)
if err != nil {
return err
}
@@ -421,14 +450,14 @@ func processPPID(p *process.Process) (string, error) {
}
// processUSER returns the effective user name of the process. This will be
-// the textual group ID, if it can be optained, or a decimal representation
+// the textual user ID, if it can be optained, or a decimal representation
// otherwise.
func processUSER(p *process.Process) (string, error) {
return process.LookupUID(p.Status.Uids[1])
}
// processRUSER returns the effective user name of the process. This will be
-// the textual group ID, if it can be optained, or a decimal representation
+// the textual user ID, if it can be optained, or a decimal representation
// otherwise.
func processRUSER(p *process.Process) (string, error) {
return process.LookupUID(p.Status.Uids[0])
@@ -557,6 +586,13 @@ func parseCAP(cap string) (string, error) {
return strings.Join(caps, ","), nil
}
+// processCAPAMB returns the set of ambient capabilties associated with
+// process p. If all capabilties are set, "full" is returned. If no
+// capability is enabled, "none" is returned.
+func processCAPAMB(p *process.Process) (string, error) {
+ return parseCAP(p.Status.CapAmb)
+}
+
// processCAPINH returns the set of inheritable capabilties associated with
// process p. If all capabilties are set, "full" is returned. If no
// capability is enabled, "none" is returned.