mirror of
https://github.com/containers/podman.git
synced 2025-10-19 12:12:36 +08:00
[v1.9] fix CVE-2022-1227
Vendor in the backports for psgo from the dedicated v1.4.0-rhel branch. Note that c/storage is also vendored by a commit. We couldn't cut a v1.19.2 for RHEL backports since Podman v1.19.1 is in Podman v1.9.3. v1.19.2 has been cut after the Podman release with changes that have not been approved for RHEL. Hence the dedicated release-1.19-podman-1.9-rhel bran in c/storage. Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
This commit is contained in:
105
vendor/github.com/containers/psgo/internal/proc/status.go
generated
vendored
105
vendor/github.com/containers/psgo/internal/proc/status.go
generated
vendored
@ -17,10 +17,14 @@ package proc
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"sync"
|
||||
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@ -175,23 +179,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: %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) {
|
||||
// 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 {
|
||||
@ -205,21 +194,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 := ioutil.ReadFile("/proc/sys/kernel/overflowuid"); err == nil {
|
||||
overflowUid = strings.TrimSpace(string(uid))
|
||||
}
|
||||
if gid, err := ioutil.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