mirror of
https://github.com/containers/podman.git
synced 2025-09-24 07:15:12 +08:00
Update vendored version of runc,buildah,containers/image
There is a compiler warning that has been fixed in the upstream, so I figured we should update to fix. Also vendor in latest buildah to get better support for running builds in rootless mode. Vendor in latest containers/image to allow daemon support to be pluggable. Signed-off-by: Daniel J Walsh <dwalsh@redhat.com> Closes: #1169 Approved by: mheon
This commit is contained in:

committed by
Atomic Bot

parent
876a30590b
commit
02e7efc2b3
13
vendor/github.com/opencontainers/runc/README.md
generated
vendored
13
vendor/github.com/opencontainers/runc/README.md
generated
vendored
@ -41,8 +41,18 @@ make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
You can also use `go get` to install to your `GOPATH`, assuming that you have a `github.com` parent folder already created under `src`:
|
||||
|
||||
```bash
|
||||
go get github.com/opencontainers/runc
|
||||
cd $GOPATH/src/github.com/opencontainers/runc
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
`runc` will be installed to `/usr/local/sbin/runc` on your system.
|
||||
|
||||
|
||||
#### Build Tags
|
||||
|
||||
`runc` supports optional build tags for compiling support of various features.
|
||||
@ -204,8 +214,7 @@ runc list
|
||||
runc delete mycontainerid
|
||||
```
|
||||
|
||||
This adds more complexity but allows higher level systems to manage runc and provides points in the containers creation to setup various settings after the container has created and/or before it is deleted.
|
||||
This is commonly used to setup the container's network stack after `create` but before `start` where the user's defined process will be running.
|
||||
This allows higher level systems to augment the containers creation logic with setup of various settings after the container is created and/or before it is deleted. For example, the container's network stack is commonly set up after `create` but before `start`.
|
||||
|
||||
#### Rootless containers
|
||||
`runc` has the ability to run containers without root privileges. This is called `rootless`. You need to pass some parameters to `runc` in order to run rootless containers. See below and compare with the previous version. Run the following commands as an ordinary user:
|
||||
|
5
vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
generated
vendored
5
vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
generated
vendored
@ -141,9 +141,10 @@ type Config struct {
|
||||
|
||||
// OomScoreAdj specifies the adjustment to be made by the kernel when calculating oom scores
|
||||
// for a process. Valid values are between the range [-1000, '1000'], where processes with
|
||||
// higher scores are preferred for being killed.
|
||||
// higher scores are preferred for being killed. If it is unset then we don't touch the current
|
||||
// value.
|
||||
// More information about kernel oom score calculation here: https://lwn.net/Articles/317814/
|
||||
OomScoreAdj int `json:"oom_score_adj"`
|
||||
OomScoreAdj *int `json:"oom_score_adj,omitempty"`
|
||||
|
||||
// UidMappings is an array of User ID mappings for User Namespaces
|
||||
UidMappings []IDMap `json:"uid_mappings"`
|
||||
|
5
vendor/github.com/opencontainers/runc/libcontainer/devices/devices.go
generated
vendored
5
vendor/github.com/opencontainers/runc/libcontainer/devices/devices.go
generated
vendored
@ -30,8 +30,9 @@ func DeviceFromPath(path, permissions string) (*configs.Device, error) {
|
||||
}
|
||||
|
||||
var (
|
||||
devNumber = stat.Rdev
|
||||
devNumber = uint64(stat.Rdev)
|
||||
major = unix.Major(devNumber)
|
||||
minor = unix.Minor(devNumber)
|
||||
)
|
||||
if major == 0 {
|
||||
return nil, ErrNotADevice
|
||||
@ -51,7 +52,7 @@ func DeviceFromPath(path, permissions string) (*configs.Device, error) {
|
||||
Type: devType,
|
||||
Path: path,
|
||||
Major: int64(major),
|
||||
Minor: int64(unix.Minor(devNumber)),
|
||||
Minor: int64(minor),
|
||||
Permissions: permissions,
|
||||
FileMode: os.FileMode(mode),
|
||||
Uid: stat.Uid,
|
||||
|
63
vendor/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c
generated
vendored
63
vendor/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c
generated
vendored
@ -505,7 +505,8 @@ void join_namespaces(char *nslist)
|
||||
|
||||
ns->fd = fd;
|
||||
ns->ns = nsflag(namespace);
|
||||
strncpy(ns->path, path, PATH_MAX);
|
||||
strncpy(ns->path, path, PATH_MAX - 1);
|
||||
ns->path[PATH_MAX - 1] = '\0';
|
||||
} while ((namespace = strtok_r(NULL, ",", &saveptr)) != NULL);
|
||||
|
||||
/*
|
||||
@ -678,17 +679,15 @@ void nsexec(void)
|
||||
/*
|
||||
* Enable setgroups(2) if we've been asked to. But we also
|
||||
* have to explicitly disable setgroups(2) if we're
|
||||
* creating a rootless container (this is required since
|
||||
* Linux 3.19).
|
||||
* creating a rootless container for single-entry mapping.
|
||||
* i.e. config.is_setgroup == false.
|
||||
* (this is required since Linux 3.19).
|
||||
*
|
||||
* For rootless multi-entry mapping, config.is_setgroup shall be true and
|
||||
* newuidmap/newgidmap shall be used.
|
||||
*/
|
||||
if (config.is_rootless && config.is_setgroup) {
|
||||
kill(child, SIGKILL);
|
||||
bail("cannot allow setgroup in an unprivileged user namespace setup");
|
||||
}
|
||||
|
||||
if (config.is_setgroup)
|
||||
update_setgroups(child, SETGROUPS_ALLOW);
|
||||
if (config.is_rootless)
|
||||
if (config.is_rootless && !config.is_setgroup)
|
||||
update_setgroups(child, SETGROUPS_DENY);
|
||||
|
||||
/* Set up mappings. */
|
||||
@ -809,25 +808,30 @@ void nsexec(void)
|
||||
if (config.namespaces)
|
||||
join_namespaces(config.namespaces);
|
||||
|
||||
/*
|
||||
* Unshare all of the namespaces. Now, it should be noted that this
|
||||
* ordering might break in the future (especially with rootless
|
||||
* containers). But for now, it's not possible to split this into
|
||||
* CLONE_NEWUSER + [the rest] because of some RHEL SELinux issues.
|
||||
*
|
||||
* Note that we don't merge this with clone() because there were
|
||||
* some old kernel versions where clone(CLONE_PARENT | CLONE_NEWPID)
|
||||
* was broken, so we'll just do it the long way anyway.
|
||||
*/
|
||||
if (unshare(config.cloneflags) < 0)
|
||||
bail("failed to unshare namespaces");
|
||||
|
||||
/*
|
||||
* Deal with user namespaces first. They are quite special, as they
|
||||
* affect our ability to unshare other namespaces and are used as
|
||||
* context for privilege checks.
|
||||
*
|
||||
* We don't unshare all namespaces in one go. The reason for this
|
||||
* is that, while the kernel documentation may claim otherwise,
|
||||
* there are certain cases where unsharing all namespaces at once
|
||||
* will result in namespace objects being owned incorrectly.
|
||||
* Ideally we should just fix these kernel bugs, but it's better to
|
||||
* be safe than sorry, and fix them separately.
|
||||
*
|
||||
* A specific case of this is that the SELinux label of the
|
||||
* internal kern-mount that mqueue uses will be incorrect if the
|
||||
* UTS namespace is cloned before the USER namespace is mapped.
|
||||
* I've also heard of similar problems with the network namespace
|
||||
* in some scenarios. This also mirrors how LXC deals with this
|
||||
* problem.
|
||||
*/
|
||||
if (config.cloneflags & CLONE_NEWUSER) {
|
||||
if (unshare(CLONE_NEWUSER) < 0)
|
||||
bail("failed to unshare user namespace");
|
||||
config.cloneflags &= ~CLONE_NEWUSER;
|
||||
|
||||
/*
|
||||
* We don't have the privileges to do any mapping here (see the
|
||||
* clone_parent rant). So signal our parent to hook us up.
|
||||
@ -853,8 +857,21 @@ void nsexec(void)
|
||||
if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) < 0)
|
||||
bail("failed to set process as dumpable");
|
||||
}
|
||||
|
||||
/* Become root in the namespace proper. */
|
||||
if (setresuid(0, 0, 0) < 0)
|
||||
bail("failed to become root in user namespace");
|
||||
}
|
||||
|
||||
/*
|
||||
* Unshare all of the namespaces. Note that we don't merge this
|
||||
* with clone() because there were some old kernel versions where
|
||||
* clone(CLONE_PARENT | CLONE_NEWPID) was broken, so we'll just do
|
||||
* it the long way.
|
||||
*/
|
||||
if (unshare(config.cloneflags) < 0)
|
||||
bail("failed to unshare namespaces");
|
||||
|
||||
/*
|
||||
* TODO: What about non-namespace clone flags that we're dropping here?
|
||||
*
|
||||
|
38
vendor/github.com/opencontainers/runc/libcontainer/system/linux.go
generated
vendored
38
vendor/github.com/opencontainers/runc/libcontainer/system/linux.go
generated
vendored
@ -3,13 +3,12 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall" // only for exec
|
||||
"unsafe"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/user"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@ -102,34 +101,43 @@ func Setctty() error {
|
||||
}
|
||||
|
||||
// RunningInUserNS detects whether we are currently running in a user namespace.
|
||||
// Copied from github.com/lxc/lxd/shared/util.go
|
||||
// Originally copied from github.com/lxc/lxd/shared/util.go
|
||||
func RunningInUserNS() bool {
|
||||
file, err := os.Open("/proc/self/uid_map")
|
||||
uidmap, err := user.CurrentProcessUIDMap()
|
||||
if err != nil {
|
||||
// This kernel-provided file only exists if user namespaces are supported
|
||||
return false
|
||||
}
|
||||
defer file.Close()
|
||||
return UIDMapInUserNS(uidmap)
|
||||
}
|
||||
|
||||
buf := bufio.NewReader(file)
|
||||
l, _, err := buf.ReadLine()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
line := string(l)
|
||||
var a, b, c int64
|
||||
fmt.Sscanf(line, "%d %d %d", &a, &b, &c)
|
||||
func UIDMapInUserNS(uidmap []user.IDMap) bool {
|
||||
/*
|
||||
* We assume we are in the initial user namespace if we have a full
|
||||
* range - 4294967295 uids starting at uid 0.
|
||||
*/
|
||||
if a == 0 && b == 0 && c == 4294967295 {
|
||||
if len(uidmap) == 1 && uidmap[0].ID == 0 && uidmap[0].ParentID == 0 && uidmap[0].Count == 4294967295 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// GetParentNSeuid returns the euid within the parent user namespace
|
||||
func GetParentNSeuid() int64 {
|
||||
euid := int64(os.Geteuid())
|
||||
uidmap, err := user.CurrentProcessUIDMap()
|
||||
if err != nil {
|
||||
// This kernel-provided file only exists if user namespaces are supported
|
||||
return euid
|
||||
}
|
||||
for _, um := range uidmap {
|
||||
if um.ID <= euid && euid <= um.ID+um.Count-1 {
|
||||
return um.ParentID + euid - um.ID
|
||||
}
|
||||
}
|
||||
return euid
|
||||
}
|
||||
|
||||
// SetSubreaper sets the value i as the subreaper setting for the calling process
|
||||
func SetSubreaper(i int) error {
|
||||
return unix.Prctl(PR_SET_CHILD_SUBREAPER, uintptr(i), 0, 0, 0)
|
||||
|
18
vendor/github.com/opencontainers/runc/libcontainer/system/unsupported.go
generated
vendored
18
vendor/github.com/opencontainers/runc/libcontainer/system/unsupported.go
generated
vendored
@ -2,8 +2,26 @@
|
||||
|
||||
package system
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/user"
|
||||
)
|
||||
|
||||
// RunningInUserNS is a stub for non-Linux systems
|
||||
// Always returns false
|
||||
func RunningInUserNS() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// UIDMapInUserNS is a stub for non-Linux systems
|
||||
// Always returns false
|
||||
func UIDMapInUserNS(uidmap []user.IDMap) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// GetParentNSeuid returns the euid within the parent user namespace
|
||||
// Always returns os.Geteuid on non-linux
|
||||
func GetParentNSeuid() int {
|
||||
return os.Geteuid()
|
||||
}
|
||||
|
62
vendor/github.com/opencontainers/runc/libcontainer/user/lookup.go
generated
vendored
62
vendor/github.com/opencontainers/runc/libcontainer/user/lookup.go
generated
vendored
@ -12,84 +12,30 @@ var (
|
||||
ErrNoGroupEntries = errors.New("no matching entries in group file")
|
||||
)
|
||||
|
||||
func lookupUser(filter func(u User) bool) (User, error) {
|
||||
// Get operating system-specific passwd reader-closer.
|
||||
passwd, err := GetPasswd()
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
defer passwd.Close()
|
||||
|
||||
// Get the users.
|
||||
users, err := ParsePasswdFilter(passwd, filter)
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
|
||||
// No user entries found.
|
||||
if len(users) == 0 {
|
||||
return User{}, ErrNoPasswdEntries
|
||||
}
|
||||
|
||||
// Assume the first entry is the "correct" one.
|
||||
return users[0], nil
|
||||
}
|
||||
|
||||
// LookupUser looks up a user by their username in /etc/passwd. If the user
|
||||
// cannot be found (or there is no /etc/passwd file on the filesystem), then
|
||||
// LookupUser returns an error.
|
||||
func LookupUser(username string) (User, error) {
|
||||
return lookupUser(func(u User) bool {
|
||||
return u.Name == username
|
||||
})
|
||||
return lookupUser(username)
|
||||
}
|
||||
|
||||
// LookupUid looks up a user by their user id in /etc/passwd. If the user cannot
|
||||
// be found (or there is no /etc/passwd file on the filesystem), then LookupId
|
||||
// returns an error.
|
||||
func LookupUid(uid int) (User, error) {
|
||||
return lookupUser(func(u User) bool {
|
||||
return u.Uid == uid
|
||||
})
|
||||
}
|
||||
|
||||
func lookupGroup(filter func(g Group) bool) (Group, error) {
|
||||
// Get operating system-specific group reader-closer.
|
||||
group, err := GetGroup()
|
||||
if err != nil {
|
||||
return Group{}, err
|
||||
}
|
||||
defer group.Close()
|
||||
|
||||
// Get the users.
|
||||
groups, err := ParseGroupFilter(group, filter)
|
||||
if err != nil {
|
||||
return Group{}, err
|
||||
}
|
||||
|
||||
// No user entries found.
|
||||
if len(groups) == 0 {
|
||||
return Group{}, ErrNoGroupEntries
|
||||
}
|
||||
|
||||
// Assume the first entry is the "correct" one.
|
||||
return groups[0], nil
|
||||
return lookupUid(uid)
|
||||
}
|
||||
|
||||
// LookupGroup looks up a group by its name in /etc/group. If the group cannot
|
||||
// be found (or there is no /etc/group file on the filesystem), then LookupGroup
|
||||
// returns an error.
|
||||
func LookupGroup(groupname string) (Group, error) {
|
||||
return lookupGroup(func(g Group) bool {
|
||||
return g.Name == groupname
|
||||
})
|
||||
return lookupGroup(groupname)
|
||||
}
|
||||
|
||||
// LookupGid looks up a group by its group id in /etc/group. If the group cannot
|
||||
// be found (or there is no /etc/group file on the filesystem), then LookupGid
|
||||
// returns an error.
|
||||
func LookupGid(gid int) (Group, error) {
|
||||
return lookupGroup(func(g Group) bool {
|
||||
return g.Gid == gid
|
||||
})
|
||||
return lookupGid(gid)
|
||||
}
|
||||
|
96
vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go
generated
vendored
96
vendor/github.com/opencontainers/runc/libcontainer/user/lookup_unix.go
generated
vendored
@ -15,6 +15,76 @@ const (
|
||||
unixGroupPath = "/etc/group"
|
||||
)
|
||||
|
||||
func lookupUser(username string) (User, error) {
|
||||
return lookupUserFunc(func(u User) bool {
|
||||
return u.Name == username
|
||||
})
|
||||
}
|
||||
|
||||
func lookupUid(uid int) (User, error) {
|
||||
return lookupUserFunc(func(u User) bool {
|
||||
return u.Uid == uid
|
||||
})
|
||||
}
|
||||
|
||||
func lookupUserFunc(filter func(u User) bool) (User, error) {
|
||||
// Get operating system-specific passwd reader-closer.
|
||||
passwd, err := GetPasswd()
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
defer passwd.Close()
|
||||
|
||||
// Get the users.
|
||||
users, err := ParsePasswdFilter(passwd, filter)
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
|
||||
// No user entries found.
|
||||
if len(users) == 0 {
|
||||
return User{}, ErrNoPasswdEntries
|
||||
}
|
||||
|
||||
// Assume the first entry is the "correct" one.
|
||||
return users[0], nil
|
||||
}
|
||||
|
||||
func lookupGroup(groupname string) (Group, error) {
|
||||
return lookupGroupFunc(func(g Group) bool {
|
||||
return g.Name == groupname
|
||||
})
|
||||
}
|
||||
|
||||
func lookupGid(gid int) (Group, error) {
|
||||
return lookupGroupFunc(func(g Group) bool {
|
||||
return g.Gid == gid
|
||||
})
|
||||
}
|
||||
|
||||
func lookupGroupFunc(filter func(g Group) bool) (Group, error) {
|
||||
// Get operating system-specific group reader-closer.
|
||||
group, err := GetGroup()
|
||||
if err != nil {
|
||||
return Group{}, err
|
||||
}
|
||||
defer group.Close()
|
||||
|
||||
// Get the users.
|
||||
groups, err := ParseGroupFilter(group, filter)
|
||||
if err != nil {
|
||||
return Group{}, err
|
||||
}
|
||||
|
||||
// No user entries found.
|
||||
if len(groups) == 0 {
|
||||
return Group{}, ErrNoGroupEntries
|
||||
}
|
||||
|
||||
// Assume the first entry is the "correct" one.
|
||||
return groups[0], nil
|
||||
}
|
||||
|
||||
func GetPasswdPath() (string, error) {
|
||||
return unixPasswdPath, nil
|
||||
}
|
||||
@ -44,3 +114,29 @@ func CurrentUser() (User, error) {
|
||||
func CurrentGroup() (Group, error) {
|
||||
return LookupGid(unix.Getgid())
|
||||
}
|
||||
|
||||
func CurrentUserSubUIDs() ([]SubID, error) {
|
||||
u, err := CurrentUser()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ParseSubIDFileFilter("/etc/subuid",
|
||||
func(entry SubID) bool { return entry.Name == u.Name })
|
||||
}
|
||||
|
||||
func CurrentGroupSubGIDs() ([]SubID, error) {
|
||||
g, err := CurrentGroup()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ParseSubIDFileFilter("/etc/subgid",
|
||||
func(entry SubID) bool { return entry.Name == g.Name })
|
||||
}
|
||||
|
||||
func CurrentProcessUIDMap() ([]IDMap, error) {
|
||||
return ParseIDMapFile("/proc/self/uid_map")
|
||||
}
|
||||
|
||||
func CurrentProcessGIDMap() ([]IDMap, error) {
|
||||
return ParseIDMapFile("/proc/self/gid_map")
|
||||
}
|
||||
|
40
vendor/github.com/opencontainers/runc/libcontainer/user/lookup_windows.go
generated
vendored
Normal file
40
vendor/github.com/opencontainers/runc/libcontainer/user/lookup_windows.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
// +build windows
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/user"
|
||||
)
|
||||
|
||||
func lookupUser(username string) (User, error) {
|
||||
u, err := user.Lookup(username)
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
return userFromOS(u)
|
||||
}
|
||||
|
||||
func lookupUid(uid int) (User, error) {
|
||||
u, err := user.LookupId(fmt.Sprintf("%d", uid))
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
return userFromOS(u)
|
||||
}
|
||||
|
||||
func lookupGroup(groupname string) (Group, error) {
|
||||
g, err := user.LookupGroup(groupname)
|
||||
if err != nil {
|
||||
return Group{}, err
|
||||
}
|
||||
return groupFromOS(g)
|
||||
}
|
||||
|
||||
func lookupGid(gid int) (Group, error) {
|
||||
g, err := user.LookupGroupId(fmt.Sprintf("%d", gid))
|
||||
if err != nil {
|
||||
return Group{}, err
|
||||
}
|
||||
return groupFromOS(g)
|
||||
}
|
173
vendor/github.com/opencontainers/runc/libcontainer/user/user.go
generated
vendored
173
vendor/github.com/opencontainers/runc/libcontainer/user/user.go
generated
vendored
@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/user"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@ -28,6 +29,28 @@ type User struct {
|
||||
Shell string
|
||||
}
|
||||
|
||||
// userFromOS converts an os/user.(*User) to local User
|
||||
//
|
||||
// (This does not include Pass, Shell or Gecos)
|
||||
func userFromOS(u *user.User) (User, error) {
|
||||
newUser := User{
|
||||
Name: u.Username,
|
||||
Home: u.HomeDir,
|
||||
}
|
||||
id, err := strconv.Atoi(u.Uid)
|
||||
if err != nil {
|
||||
return newUser, err
|
||||
}
|
||||
newUser.Uid = id
|
||||
|
||||
id, err = strconv.Atoi(u.Gid)
|
||||
if err != nil {
|
||||
return newUser, err
|
||||
}
|
||||
newUser.Gid = id
|
||||
return newUser, nil
|
||||
}
|
||||
|
||||
type Group struct {
|
||||
Name string
|
||||
Pass string
|
||||
@ -35,12 +58,46 @@ type Group struct {
|
||||
List []string
|
||||
}
|
||||
|
||||
// groupFromOS converts an os/user.(*Group) to local Group
|
||||
//
|
||||
// (This does not include Pass, Shell or Gecos)
|
||||
func groupFromOS(g *user.Group) (Group, error) {
|
||||
newGroup := Group{
|
||||
Name: g.Name,
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(g.Gid)
|
||||
if err != nil {
|
||||
return newGroup, err
|
||||
}
|
||||
newGroup.Gid = id
|
||||
|
||||
return newGroup, nil
|
||||
}
|
||||
|
||||
// SubID represents an entry in /etc/sub{u,g}id
|
||||
type SubID struct {
|
||||
Name string
|
||||
SubID int64
|
||||
Count int64
|
||||
}
|
||||
|
||||
// IDMap represents an entry in /proc/PID/{u,g}id_map
|
||||
type IDMap struct {
|
||||
ID int64
|
||||
ParentID int64
|
||||
Count int64
|
||||
}
|
||||
|
||||
func parseLine(line string, v ...interface{}) {
|
||||
if line == "" {
|
||||
parseParts(strings.Split(line, ":"), v...)
|
||||
}
|
||||
|
||||
func parseParts(parts []string, v ...interface{}) {
|
||||
if len(parts) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
parts := strings.Split(line, ":")
|
||||
for i, p := range parts {
|
||||
// Ignore cases where we don't have enough fields to populate the arguments.
|
||||
// Some configuration files like to misbehave.
|
||||
@ -56,6 +113,8 @@ func parseLine(line string, v ...interface{}) {
|
||||
case *int:
|
||||
// "numbers", with conversion errors ignored because of some misbehaving configuration files.
|
||||
*e, _ = strconv.Atoi(p)
|
||||
case *int64:
|
||||
*e, _ = strconv.ParseInt(p, 10, 64)
|
||||
case *[]string:
|
||||
// Comma-separated lists.
|
||||
if p != "" {
|
||||
@ -65,7 +124,7 @@ func parseLine(line string, v ...interface{}) {
|
||||
}
|
||||
default:
|
||||
// Someone goof'd when writing code using this function. Scream so they can hear us.
|
||||
panic(fmt.Sprintf("parseLine only accepts {*string, *int, *[]string} as arguments! %#v is not a pointer!", e))
|
||||
panic(fmt.Sprintf("parseLine only accepts {*string, *int, *int64, *[]string} as arguments! %#v is not a pointer!", e))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -439,3 +498,111 @@ func GetAdditionalGroupsPath(additionalGroups []string, groupPath string) ([]int
|
||||
}
|
||||
return GetAdditionalGroups(additionalGroups, group)
|
||||
}
|
||||
|
||||
func ParseSubIDFile(path string) ([]SubID, error) {
|
||||
subid, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer subid.Close()
|
||||
return ParseSubID(subid)
|
||||
}
|
||||
|
||||
func ParseSubID(subid io.Reader) ([]SubID, error) {
|
||||
return ParseSubIDFilter(subid, nil)
|
||||
}
|
||||
|
||||
func ParseSubIDFileFilter(path string, filter func(SubID) bool) ([]SubID, error) {
|
||||
subid, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer subid.Close()
|
||||
return ParseSubIDFilter(subid, filter)
|
||||
}
|
||||
|
||||
func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) {
|
||||
if r == nil {
|
||||
return nil, fmt.Errorf("nil source for subid-formatted data")
|
||||
}
|
||||
|
||||
var (
|
||||
s = bufio.NewScanner(r)
|
||||
out = []SubID{}
|
||||
)
|
||||
|
||||
for s.Scan() {
|
||||
if err := s.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
line := strings.TrimSpace(s.Text())
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// see: man 5 subuid
|
||||
p := SubID{}
|
||||
parseLine(line, &p.Name, &p.SubID, &p.Count)
|
||||
|
||||
if filter == nil || filter(p) {
|
||||
out = append(out, p)
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func ParseIDMapFile(path string) ([]IDMap, error) {
|
||||
r, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer r.Close()
|
||||
return ParseIDMap(r)
|
||||
}
|
||||
|
||||
func ParseIDMap(r io.Reader) ([]IDMap, error) {
|
||||
return ParseIDMapFilter(r, nil)
|
||||
}
|
||||
|
||||
func ParseIDMapFileFilter(path string, filter func(IDMap) bool) ([]IDMap, error) {
|
||||
r, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer r.Close()
|
||||
return ParseIDMapFilter(r, filter)
|
||||
}
|
||||
|
||||
func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) {
|
||||
if r == nil {
|
||||
return nil, fmt.Errorf("nil source for idmap-formatted data")
|
||||
}
|
||||
|
||||
var (
|
||||
s = bufio.NewScanner(r)
|
||||
out = []IDMap{}
|
||||
)
|
||||
|
||||
for s.Scan() {
|
||||
if err := s.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
line := strings.TrimSpace(s.Text())
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// see: man 7 user_namespaces
|
||||
p := IDMap{}
|
||||
parseParts(strings.Fields(line), &p.ID, &p.ParentID, &p.Count)
|
||||
|
||||
if filter == nil || filter(p) {
|
||||
out = append(out, p)
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
2
vendor/github.com/opencontainers/runc/vendor.conf
generated
vendored
2
vendor/github.com/opencontainers/runc/vendor.conf
generated
vendored
@ -21,5 +21,5 @@ github.com/urfave/cli d53eb991652b1d438abdd34ce4bfa3ef1539108e
|
||||
golang.org/x/sys 7ddbeae9ae08c6a06a59597f0c9edbc5ff2444ce https://github.com/golang/sys
|
||||
|
||||
# console dependencies
|
||||
github.com/containerd/console 84eeaae905fa414d03e07bcd6c8d3f19e7cf180e
|
||||
github.com/containerd/console 2748ece16665b45a47f884001d5831ec79703880
|
||||
github.com/pkg/errors v0.8.0
|
||||
|
Reference in New Issue
Block a user