mirror of
https://github.com/containers/podman.git
synced 2025-11-17 03:27:47 +08:00
vendor c/psgo@v1.7.2
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
16
vendor/github.com/containers/psgo/internal/proc/ns.go
generated
vendored
16
vendor/github.com/containers/psgo/internal/proc/ns.go
generated
vendored
@@ -19,13 +19,9 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
type IDMap struct {
|
||||
ContainerID int
|
||||
HostID int
|
||||
Size int
|
||||
}
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
)
|
||||
|
||||
// ParsePIDNamespace returns the content of /proc/$pid/ns/pid.
|
||||
func ParsePIDNamespace(pid string) (string, error) {
|
||||
@@ -46,14 +42,14 @@ func ParseUserNamespace(pid string) (string, error) {
|
||||
}
|
||||
|
||||
// ReadMappings reads the user namespace mappings at the specified path
|
||||
func ReadMappings(path string) ([]IDMap, error) {
|
||||
func ReadMappings(path string) ([]idtools.IDMap, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
mappings := []IDMap{}
|
||||
var mappings []idtools.IDMap
|
||||
|
||||
buf := bufio.NewReader(file)
|
||||
for {
|
||||
@@ -68,10 +64,10 @@ func ReadMappings(path string) ([]IDMap, error) {
|
||||
return mappings, nil
|
||||
}
|
||||
|
||||
containerID, hostID, size := 0, 0, 0
|
||||
var containerID, hostID, size int
|
||||
if _, err := fmt.Sscanf(string(line), "%d %d %d", &containerID, &hostID, &size); err != nil {
|
||||
return nil, fmt.Errorf("cannot parse %s: %w", string(line), err)
|
||||
}
|
||||
mappings = append(mappings, IDMap{ContainerID: containerID, HostID: hostID, Size: size})
|
||||
mappings = append(mappings, idtools.IDMap{ContainerID: containerID, HostID: hostID, Size: size})
|
||||
}
|
||||
}
|
||||
|
||||
104
vendor/github.com/containers/psgo/internal/proc/status.go
generated
vendored
104
vendor/github.com/containers/psgo/internal/proc/status.go
generated
vendored
@@ -18,8 +18,11 @@ import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
)
|
||||
|
||||
// Status is a direct translation of a `/proc/[pid]/status`, which provides much
|
||||
@@ -173,23 +176,8 @@ type Status struct {
|
||||
NonvoluntaryCtxtSwitches string
|
||||
}
|
||||
|
||||
// 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: %w", 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) {
|
||||
// readStatus returns the content of /proc/pid/status as a string slice.
|
||||
func readStatus(pid string) ([]string, error) {
|
||||
path := fmt.Sprintf("/proc/%s/status", pid)
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
@@ -203,21 +191,81 @@ func readStatusDefault(pid string) ([]string, error) {
|
||||
return lines, nil
|
||||
}
|
||||
|
||||
// ParseStatus parses the /proc/$pid/status file and returns a *Status.
|
||||
func ParseStatus(pid string, joinUserNS bool) (*Status, error) {
|
||||
var lines []string
|
||||
var err error
|
||||
|
||||
if joinUserNS {
|
||||
lines, err = readStatusUserNS(pid)
|
||||
} else {
|
||||
lines, err = readStatusDefault(pid)
|
||||
// mapField maps a single string-typed ID field given the set of mappings. If
|
||||
// no mapping exists, the overflow uid/gid is used.
|
||||
func mapStatusField(field *string, mapping []idtools.IDMap, overflow string) {
|
||||
hostId, err := strconv.Atoi(*field)
|
||||
if err != nil {
|
||||
*field = overflow
|
||||
return
|
||||
}
|
||||
contId, err := idtools.RawToContainer(hostId, mapping)
|
||||
if err != nil {
|
||||
*field = overflow
|
||||
return
|
||||
}
|
||||
*field = strconv.Itoa(contId)
|
||||
}
|
||||
|
||||
var (
|
||||
overflowOnce sync.Once
|
||||
overflowUid = "65534"
|
||||
overflowGid = "65534"
|
||||
)
|
||||
|
||||
func overflowIds() (string, string) {
|
||||
overflowOnce.Do(func() {
|
||||
if uid, err := os.ReadFile("/proc/sys/kernel/overflowuid"); err == nil {
|
||||
overflowUid = strings.TrimSpace(string(uid))
|
||||
}
|
||||
if gid, err := os.ReadFile("/proc/sys/kernel/overflowgid"); err == nil {
|
||||
overflowGid = strings.TrimSpace(string(gid))
|
||||
}
|
||||
})
|
||||
return overflowUid, overflowGid
|
||||
}
|
||||
|
||||
// mapStatus takes a Status struct and remaps all of the relevant fields to
|
||||
// match the user namespace of the target process.
|
||||
func mapStatus(pid string, status *Status) (*Status, error) {
|
||||
uidMap, err := ReadMappings(fmt.Sprintf("/proc/%s/uid_map", pid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parseStatus(pid, lines)
|
||||
gidMap, err := ReadMappings(fmt.Sprintf("/proc/%s/gid_map", pid))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
overflowUid, overflowGid := overflowIds()
|
||||
for i := range status.Uids {
|
||||
mapStatusField(&status.Uids[i], uidMap, overflowUid)
|
||||
}
|
||||
for i := range status.Gids {
|
||||
mapStatusField(&status.Gids[i], gidMap, overflowGid)
|
||||
}
|
||||
for i := range status.Groups {
|
||||
mapStatusField(&status.Groups[i], gidMap, overflowGid)
|
||||
}
|
||||
return status, nil
|
||||
}
|
||||
|
||||
// ParseStatus parses the /proc/$pid/status file and returns a *Status.
|
||||
func ParseStatus(pid string, mapUserNS bool) (*Status, error) {
|
||||
lines, err := readStatus(pid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
status, err := parseStatus(pid, lines)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if mapUserNS {
|
||||
status, err = mapStatus(pid, status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return status, nil
|
||||
}
|
||||
|
||||
// parseStatus extracts data from lines and returns a *Status.
|
||||
|
||||
Reference in New Issue
Block a user