mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
vendor: github.com/opencontainers/runc v1.0.1
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
parent
f50c7644cf
commit
1256aa0241
16 changed files with 167 additions and 278 deletions
|
@ -87,7 +87,7 @@ google.golang.org/grpc f495f5b15ae7ccda3b38c53a1bfc
|
|||
# the containerd project first, and update both after that is merged.
|
||||
# This commit does not need to match RUNC_COMMIT as it is used for helper
|
||||
# packages but should be newer or equal.
|
||||
github.com/opencontainers/runc b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7 # v1.0.0-rc95
|
||||
github.com/opencontainers/runc 4144b63817ebcc5b358fc2c8ef95f7cddd709aa7 # v1.0.1
|
||||
github.com/opencontainers/runtime-spec 1c3f411f041711bbeecf35ff7e93461ea6789220 # v1.0.3-0.20210326190908-1c3f411f0417
|
||||
github.com/opencontainers/image-spec d60099175f88c47cd379c4738d158884749ed235 # v1.0.1
|
||||
github.com/cyphar/filepath-securejoin a261ee33d7a517f054effbf451841abaafe3e0fd # v0.2.2
|
||||
|
|
12
vendor/github.com/opencontainers/runc/go.mod
generated
vendored
12
vendor/github.com/opencontainers/runc/go.mod
generated
vendored
|
@ -3,26 +3,26 @@ module github.com/opencontainers/runc
|
|||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/bits-and-blooms/bitset v1.2.0
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0
|
||||
github.com/cilium/ebpf v0.5.0
|
||||
github.com/cilium/ebpf v0.6.2
|
||||
github.com/containerd/console v1.0.2
|
||||
github.com/coreos/go-systemd/v22 v22.3.1
|
||||
github.com/coreos/go-systemd/v22 v22.3.2
|
||||
github.com/cyphar/filepath-securejoin v0.2.2
|
||||
github.com/docker/go-units v0.4.0
|
||||
github.com/godbus/dbus/v5 v5.0.4
|
||||
github.com/moby/sys/mountinfo v0.4.1
|
||||
github.com/mrunalp/fileutils v0.5.0
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
|
||||
github.com/opencontainers/selinux v1.8.0
|
||||
github.com/opencontainers/selinux v1.8.2
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/seccomp/libseccomp-golang v0.9.1
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
|
||||
// NOTE: urfave/cli must be <= v1.22.1 due to a regression: https://github.com/urfave/cli/issues/1092
|
||||
github.com/urfave/cli v1.22.1
|
||||
github.com/vishvananda/netlink v1.1.0
|
||||
github.com/willf/bitset v1.1.11
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887
|
||||
google.golang.org/protobuf v1.25.0
|
||||
google.golang.org/protobuf v1.26.0
|
||||
)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package fscommon
|
||||
package cgroups
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -10,6 +11,54 @@ import (
|
|||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// OpenFile opens a cgroup file in a given dir with given flags.
|
||||
// It is supposed to be used for cgroup files only.
|
||||
func OpenFile(dir, file string, flags int) (*os.File, error) {
|
||||
if dir == "" {
|
||||
return nil, errors.Errorf("no directory specified for %s", file)
|
||||
}
|
||||
return openFile(dir, file, flags)
|
||||
}
|
||||
|
||||
// ReadFile reads data from a cgroup file in dir.
|
||||
// It is supposed to be used for cgroup files only.
|
||||
func ReadFile(dir, file string) (string, error) {
|
||||
fd, err := OpenFile(dir, file, unix.O_RDONLY)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer fd.Close()
|
||||
var buf bytes.Buffer
|
||||
|
||||
_, err = buf.ReadFrom(fd)
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
// WriteFile writes data to a cgroup file in dir.
|
||||
// It is supposed to be used for cgroup files only.
|
||||
func WriteFile(dir, file, data string) error {
|
||||
fd, err := OpenFile(dir, file, unix.O_WRONLY)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fd.Close()
|
||||
if err := retryingWriteFile(fd, data); err != nil {
|
||||
return errors.Wrapf(err, "failed to write %q", data)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func retryingWriteFile(fd *os.File, data string) error {
|
||||
for {
|
||||
_, err := fd.Write([]byte(data))
|
||||
if errors.Is(err, unix.EINTR) {
|
||||
logrus.Infof("interrupted while writing %s to %s", data, fd.Name())
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
cgroupfsDir = "/sys/fs/cgroup"
|
||||
cgroupfsPrefix = cgroupfsDir + "/"
|
||||
|
@ -28,7 +77,8 @@ var (
|
|||
func prepareOpenat2() error {
|
||||
prepOnce.Do(func() {
|
||||
fd, err := unix.Openat2(-1, cgroupfsDir, &unix.OpenHow{
|
||||
Flags: unix.O_DIRECTORY | unix.O_PATH})
|
||||
Flags: unix.O_DIRECTORY | unix.O_PATH,
|
||||
})
|
||||
if err != nil {
|
||||
prepErr = &os.PathError{Op: "openat2", Path: cgroupfsDir, Err: err}
|
||||
if err != unix.ENOSYS {
|
||||
|
@ -52,7 +102,6 @@ func prepareOpenat2() error {
|
|||
// cgroupv2 has a single mountpoint and no "cpu,cpuacct" symlinks
|
||||
resolveFlags |= unix.RESOLVE_NO_XDEV | unix.RESOLVE_NO_SYMLINKS
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
return prepErr
|
||||
|
@ -60,10 +109,7 @@ func prepareOpenat2() error {
|
|||
|
||||
// OpenFile opens a cgroup file in a given dir with given flags.
|
||||
// It is supposed to be used for cgroup files only.
|
||||
func OpenFile(dir, file string, flags int) (*os.File, error) {
|
||||
if dir == "" {
|
||||
return nil, errors.Errorf("no directory specified for %s", file)
|
||||
}
|
||||
func openFile(dir, file string, flags int) (*os.File, error) {
|
||||
mode := os.FileMode(0)
|
||||
if TestMode && flags&os.O_WRONLY != 0 {
|
||||
// "emulate" cgroup fs for unit tests
|
51
vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/fscommon.go
generated
vendored
51
vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/fscommon.go
generated
vendored
|
@ -1,51 +0,0 @@
|
|||
// +build linux
|
||||
|
||||
package fscommon
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// WriteFile writes data to a cgroup file in dir.
|
||||
// It is supposed to be used for cgroup files only.
|
||||
func WriteFile(dir, file, data string) error {
|
||||
fd, err := OpenFile(dir, file, unix.O_WRONLY)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fd.Close()
|
||||
if err := retryingWriteFile(fd, data); err != nil {
|
||||
return errors.Wrapf(err, "failed to write %q", data)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadFile reads data from a cgroup file in dir.
|
||||
// It is supposed to be used for cgroup files only.
|
||||
func ReadFile(dir, file string) (string, error) {
|
||||
fd, err := OpenFile(dir, file, unix.O_RDONLY)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer fd.Close()
|
||||
var buf bytes.Buffer
|
||||
|
||||
_, err = buf.ReadFrom(fd)
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
func retryingWriteFile(fd *os.File, data string) error {
|
||||
for {
|
||||
_, err := fd.Write([]byte(data))
|
||||
if errors.Is(err, unix.EINTR) {
|
||||
logrus.Infof("interrupted while writing %s to %s", data, fd.Name())
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
122
vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/utils.go
generated
vendored
122
vendor/github.com/opencontainers/runc/libcontainer/cgroups/fscommon/utils.go
generated
vendored
|
@ -1,122 +0,0 @@
|
|||
// +build linux
|
||||
|
||||
package fscommon
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotValidFormat = errors.New("line is not a valid key value format")
|
||||
)
|
||||
|
||||
// ParseUint converts a string to an uint64 integer.
|
||||
// Negative values are returned at zero as, due to kernel bugs,
|
||||
// some of the memory cgroup stats can be negative.
|
||||
func ParseUint(s string, base, bitSize int) (uint64, error) {
|
||||
value, err := strconv.ParseUint(s, base, bitSize)
|
||||
if err != nil {
|
||||
intValue, intErr := strconv.ParseInt(s, base, bitSize)
|
||||
// 1. Handle negative values greater than MinInt64 (and)
|
||||
// 2. Handle negative values lesser than MinInt64
|
||||
if intErr == nil && intValue < 0 {
|
||||
return 0, nil
|
||||
} else if intErr != nil && intErr.(*strconv.NumError).Err == strconv.ErrRange && intValue < 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return value, err
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
|
||||
// ParseKeyValue parses a space-separated "name value" kind of cgroup
|
||||
// parameter and returns its key as a string, and its value as uint64
|
||||
// (ParseUint is used to convert the value). For example,
|
||||
// "io_service_bytes 1234" will be returned as "io_service_bytes", 1234.
|
||||
func ParseKeyValue(t string) (string, uint64, error) {
|
||||
parts := strings.SplitN(t, " ", 3)
|
||||
if len(parts) != 2 {
|
||||
return "", 0, fmt.Errorf("line %q is not in key value format", t)
|
||||
}
|
||||
|
||||
value, err := ParseUint(parts[1], 10, 64)
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("unable to convert to uint64: %v", err)
|
||||
}
|
||||
|
||||
return parts[0], value, nil
|
||||
}
|
||||
|
||||
// GetValueByKey reads a key-value pairs from the specified cgroup file,
|
||||
// and returns a value of the specified key. ParseUint is used for value
|
||||
// conversion.
|
||||
func GetValueByKey(path, file, key string) (uint64, error) {
|
||||
content, err := ReadFile(path, file)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
lines := strings.Split(string(content), "\n")
|
||||
for _, line := range lines {
|
||||
arr := strings.Split(line, " ")
|
||||
if len(arr) == 2 && arr[0] == key {
|
||||
return ParseUint(arr[1], 10, 64)
|
||||
}
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// GetCgroupParamUint reads a single uint64 value from the specified cgroup file.
|
||||
// If the value read is "max", the math.MaxUint64 is returned.
|
||||
func GetCgroupParamUint(path, file string) (uint64, error) {
|
||||
contents, err := GetCgroupParamString(path, file)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
contents = strings.TrimSpace(contents)
|
||||
if contents == "max" {
|
||||
return math.MaxUint64, nil
|
||||
}
|
||||
|
||||
res, err := ParseUint(contents, 10, 64)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("unable to parse file %q", path+"/"+file)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// GetCgroupParamInt reads a single int64 value from specified cgroup file.
|
||||
// If the value read is "max", the math.MaxInt64 is returned.
|
||||
func GetCgroupParamInt(path, file string) (int64, error) {
|
||||
contents, err := ReadFile(path, file)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
contents = strings.TrimSpace(contents)
|
||||
if contents == "max" {
|
||||
return math.MaxInt64, nil
|
||||
}
|
||||
|
||||
res, err := strconv.ParseInt(contents, 10, 64)
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("unable to parse %q as a int from Cgroup file %q", contents, path+"/"+file)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// GetCgroupParamString reads a string from the specified cgroup file.
|
||||
func GetCgroupParamString(path, file string) (string, error) {
|
||||
contents, err := ReadFile(path, file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.TrimSpace(contents), nil
|
||||
}
|
6
vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
generated
vendored
6
vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
generated
vendored
|
@ -15,7 +15,6 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
|
||||
"github.com/opencontainers/runc/libcontainer/userns"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
|
@ -88,7 +87,7 @@ func GetAllSubsystems() ([]string, error) {
|
|||
// - freezer: implemented in kernel 5.2
|
||||
// We assume these are always available, as it is hard to detect availability.
|
||||
pseudo := []string{"devices", "freezer"}
|
||||
data, err := fscommon.ReadFile("/sys/fs/cgroup", "cgroup.controllers")
|
||||
data, err := ReadFile("/sys/fs/cgroup", "cgroup.controllers")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -267,7 +266,6 @@ func RemovePaths(paths map[string]string) (err error) {
|
|||
case retries - 1:
|
||||
logrus.WithError(err).Error("Failed to remove cgroup")
|
||||
}
|
||||
|
||||
}
|
||||
_, err := os.Stat(p)
|
||||
// We need this strange way of checking cgroups existence because
|
||||
|
@ -376,7 +374,7 @@ func WriteCgroupProc(dir string, pid int) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
file, err := fscommon.OpenFile(dir, CgroupProcesses, os.O_WRONLY)
|
||||
file, err := OpenFile(dir, CgroupProcesses, os.O_WRONLY)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
|
||||
}
|
||||
|
|
10
vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
generated
vendored
10
vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
generated
vendored
|
@ -13,12 +13,12 @@ const (
|
|||
Thawed FreezerState = "THAWED"
|
||||
)
|
||||
|
||||
// Cgroup holds properties of a cgroup on Linux.
|
||||
type Cgroup struct {
|
||||
// Deprecated, use Path instead
|
||||
// Name specifies the name of the cgroup
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// name of parent of cgroup or slice
|
||||
// Deprecated, use Path instead
|
||||
// Parent specifies the name of parent of cgroup or slice
|
||||
Parent string `json:"parent,omitempty"`
|
||||
|
||||
// Path specifies the path to cgroups that are created and/or joined by the container.
|
||||
|
@ -127,8 +127,8 @@ type Resources struct {
|
|||
|
||||
// SkipDevices allows to skip configuring device permissions.
|
||||
// Used by e.g. kubelet while creating a parent cgroup (kubepods)
|
||||
// common for many containers.
|
||||
// common for many containers, and by runc update.
|
||||
//
|
||||
// NOTE it is impossible to start a container which has this flag set.
|
||||
SkipDevices bool `json:"skip_devices"`
|
||||
SkipDevices bool `json:"-"`
|
||||
}
|
||||
|
|
4
vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go
generated
vendored
4
vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go
generated
vendored
|
@ -2,7 +2,7 @@
|
|||
|
||||
package configs
|
||||
|
||||
// Cgroup holds properties of a cgroup on Linux
|
||||
// TODO Windows: This can ultimately be entirely factored out on Windows as
|
||||
// cgroups are a Unix-specific construct.
|
||||
type Cgroup struct {
|
||||
}
|
||||
type Cgroup struct{}
|
||||
|
|
10
vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
generated
vendored
10
vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
generated
vendored
|
@ -208,9 +208,11 @@ type Config struct {
|
|||
RootlessCgroups bool `json:"rootless_cgroups,omitempty"`
|
||||
}
|
||||
|
||||
type HookName string
|
||||
type HookList []Hook
|
||||
type Hooks map[HookName]HookList
|
||||
type (
|
||||
HookName string
|
||||
HookList []Hook
|
||||
Hooks map[HookName]HookList
|
||||
)
|
||||
|
||||
const (
|
||||
// Prestart commands are executed after the container namespaces are created,
|
||||
|
@ -387,7 +389,7 @@ func (c Command) Run(s *specs.State) error {
|
|||
case err := <-errC:
|
||||
return err
|
||||
case <-timerCh:
|
||||
cmd.Process.Kill()
|
||||
_ = cmd.Process.Kill()
|
||||
<-errC
|
||||
return fmt.Errorf("hook ran past specified timeout of %.1fs", c.Timeout.Seconds())
|
||||
}
|
||||
|
|
17
vendor/github.com/opencontainers/runc/libcontainer/configs/devices.go
generated
vendored
17
vendor/github.com/opencontainers/runc/libcontainer/configs/devices.go
generated
vendored
|
@ -1,17 +0,0 @@
|
|||
package configs
|
||||
|
||||
import "github.com/opencontainers/runc/libcontainer/devices"
|
||||
|
||||
type (
|
||||
// Deprecated: use libcontainer/devices.Device
|
||||
Device = devices.Device
|
||||
|
||||
// Deprecated: use libcontainer/devices.Rule
|
||||
DeviceRule = devices.Rule
|
||||
|
||||
// Deprecated: use libcontainer/devices.Type
|
||||
DeviceType = devices.Type
|
||||
|
||||
// Deprecated: use libcontainer/devices.Permissions
|
||||
DevicePermissions = devices.Permissions
|
||||
)
|
2
vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go
generated
vendored
2
vendor/github.com/opencontainers/runc/libcontainer/configs/mount.go
generated
vendored
|
@ -3,7 +3,7 @@ package configs
|
|||
const (
|
||||
// EXT_COPYUP is a directive to copy up the contents of a directory when
|
||||
// a tmpfs is mounted over it.
|
||||
EXT_COPYUP = 1 << iota
|
||||
EXT_COPYUP = 1 << iota //nolint:golint // ignore "don't use ALL_CAPS" warning
|
||||
)
|
||||
|
||||
type Mount struct {
|
||||
|
|
3
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go
generated
vendored
3
vendor/github.com/opencontainers/runc/libcontainer/configs/namespaces_unsupported.go
generated
vendored
|
@ -4,5 +4,4 @@ package configs
|
|||
|
||||
// Namespace defines configuration for each namespace. It specifies an
|
||||
// alternate path that is able to be joined via setns.
|
||||
type Namespace struct {
|
||||
}
|
||||
type Namespace struct{}
|
||||
|
|
13
vendor/github.com/opencontainers/runc/libcontainer/configs/network.go
generated
vendored
13
vendor/github.com/opencontainers/runc/libcontainer/configs/network.go
generated
vendored
|
@ -50,7 +50,10 @@ type Network struct {
|
|||
HairpinMode bool `json:"hairpin_mode"`
|
||||
}
|
||||
|
||||
// Routes can be specified to create entries in the route table as the container is started
|
||||
// Route defines a routing table entry.
|
||||
//
|
||||
// Routes can be specified to create entries in the routing table as the container
|
||||
// is started.
|
||||
//
|
||||
// All of destination, source, and gateway should be either IPv4 or IPv6.
|
||||
// One of the three options must be present, and omitted entries will use their
|
||||
|
@ -58,15 +61,15 @@ type Network struct {
|
|||
// gateway to 1.2.3.4 and the interface to eth0 will set up a standard
|
||||
// destination of 0.0.0.0(or *) when viewed in the route table.
|
||||
type Route struct {
|
||||
// Sets the destination and mask, should be a CIDR. Accepts IPv4 and IPv6
|
||||
// Destination specifies the destination IP address and mask in the CIDR form.
|
||||
Destination string `json:"destination"`
|
||||
|
||||
// Sets the source and mask, should be a CIDR. Accepts IPv4 and IPv6
|
||||
// Source specifies the source IP address and mask in the CIDR form.
|
||||
Source string `json:"source"`
|
||||
|
||||
// Sets the gateway. Accepts IPv4 and IPv6
|
||||
// Gateway specifies the gateway IP address.
|
||||
Gateway string `json:"gateway"`
|
||||
|
||||
// The device to set this route up for, for example: eth0
|
||||
// InterfaceName specifies the device to set this route up for, for example eth0.
|
||||
InterfaceName string `json:"interface_name"`
|
||||
}
|
||||
|
|
11
vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go
generated
vendored
11
vendor/github.com/opencontainers/runc/libcontainer/devices/device_unix.go
generated
vendored
|
@ -11,10 +11,8 @@ import (
|
|||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNotADevice denotes that a file is not a valid linux device.
|
||||
ErrNotADevice = errors.New("not a device node")
|
||||
)
|
||||
// ErrNotADevice denotes that a file is not a valid linux device.
|
||||
var ErrNotADevice = errors.New("not a device node")
|
||||
|
||||
// Testing dependencies
|
||||
var (
|
||||
|
@ -29,8 +27,9 @@ func mkDev(d *Rule) (uint64, error) {
|
|||
return unix.Mkdev(uint32(d.Major), uint32(d.Minor)), nil
|
||||
}
|
||||
|
||||
// Given the path to a device and its cgroup_permissions(which cannot be easily queried) look up the
|
||||
// information about a linux device and return that information as a Device struct.
|
||||
// DeviceFromPath takes the path to a device and its cgroup_permissions (which
|
||||
// cannot be easily queried) to look up the information about a linux device
|
||||
// and returns that information as a Device struct.
|
||||
func DeviceFromPath(path, permissions string) (*Device, error) {
|
||||
var stat unix.Stat_t
|
||||
err := unixLstat(path, &stat)
|
||||
|
|
6
vendor/github.com/opencontainers/runc/libcontainer/nsenter/test/escape.go
generated
vendored
6
vendor/github.com/opencontainers/runc/libcontainer/nsenter/test/escape.go
generated
vendored
|
@ -14,7 +14,7 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
|
||||
func testEscapeJsonString(t *testing.T, input, want string) {
|
||||
func testEscapeJSONString(t *testing.T, input, want string) {
|
||||
in := C.CString(input)
|
||||
out := C.escape_json_string(in)
|
||||
got := C.GoString(out)
|
||||
|
@ -25,7 +25,7 @@ func testEscapeJsonString(t *testing.T, input, want string) {
|
|||
}
|
||||
}
|
||||
|
||||
func testEscapeJson(t *testing.T) {
|
||||
func testEscapeJSON(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input, output string
|
||||
}{
|
||||
|
@ -48,6 +48,6 @@ func testEscapeJson(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
testEscapeJsonString(t, tc.input, tc.output)
|
||||
testEscapeJSONString(t, tc.input, tc.output)
|
||||
}
|
||||
}
|
||||
|
|
116
vendor/github.com/opencontainers/runc/libcontainer/user/user.go
generated
vendored
116
vendor/github.com/opencontainers/runc/libcontainer/user/user.go
generated
vendored
|
@ -2,6 +2,7 @@ package user
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -11,19 +12,17 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
minId = 0
|
||||
maxId = 1<<31 - 1 //for 32-bit systems compatibility
|
||||
minID = 0
|
||||
maxID = 1<<31 - 1 // for 32-bit systems compatibility
|
||||
)
|
||||
|
||||
var (
|
||||
// The current operating system does not provide the required data for user lookups.
|
||||
ErrUnsupported = errors.New("user lookup: operating system does not provide passwd-formatted data")
|
||||
|
||||
// No matching entries found in file.
|
||||
// ErrNoPasswdEntries is returned if no matching entries were found in /etc/group.
|
||||
ErrNoPasswdEntries = errors.New("no matching entries in passwd file")
|
||||
ErrNoGroupEntries = errors.New("no matching entries in group file")
|
||||
|
||||
ErrRange = fmt.Errorf("uids and gids must be in range %d-%d", minId, maxId)
|
||||
// ErrNoGroupEntries is returned if no matching entries were found in /etc/passwd.
|
||||
ErrNoGroupEntries = errors.New("no matching entries in group file")
|
||||
// ErrRange is returned if a UID or GID is outside of the valid range.
|
||||
ErrRange = fmt.Errorf("uids and gids must be in range %d-%d", minID, maxID)
|
||||
)
|
||||
|
||||
type User struct {
|
||||
|
@ -57,11 +56,11 @@ type IDMap struct {
|
|||
Count int64
|
||||
}
|
||||
|
||||
func parseLine(line string, v ...interface{}) {
|
||||
parseParts(strings.Split(line, ":"), v...)
|
||||
func parseLine(line []byte, v ...interface{}) {
|
||||
parseParts(bytes.Split(line, []byte(":")), v...)
|
||||
}
|
||||
|
||||
func parseParts(parts []string, v ...interface{}) {
|
||||
func parseParts(parts [][]byte, v ...interface{}) {
|
||||
if len(parts) == 0 {
|
||||
return
|
||||
}
|
||||
|
@ -77,16 +76,16 @@ func parseParts(parts []string, v ...interface{}) {
|
|||
// This is legit.
|
||||
switch e := v[i].(type) {
|
||||
case *string:
|
||||
*e = p
|
||||
*e = string(p)
|
||||
case *int:
|
||||
// "numbers", with conversion errors ignored because of some misbehaving configuration files.
|
||||
*e, _ = strconv.Atoi(p)
|
||||
*e, _ = strconv.Atoi(string(p))
|
||||
case *int64:
|
||||
*e, _ = strconv.ParseInt(p, 10, 64)
|
||||
*e, _ = strconv.ParseInt(string(p), 10, 64)
|
||||
case *[]string:
|
||||
// Comma-separated lists.
|
||||
if p != "" {
|
||||
*e = strings.Split(p, ",")
|
||||
if len(p) != 0 {
|
||||
*e = strings.Split(string(p), ",")
|
||||
} else {
|
||||
*e = []string{}
|
||||
}
|
||||
|
@ -130,8 +129,8 @@ func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
|
|||
)
|
||||
|
||||
for s.Scan() {
|
||||
line := strings.TrimSpace(s.Text())
|
||||
if line == "" {
|
||||
line := bytes.TrimSpace(s.Bytes())
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -181,15 +180,53 @@ func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
|
|||
if r == nil {
|
||||
return nil, fmt.Errorf("nil source for group-formatted data")
|
||||
}
|
||||
rd := bufio.NewReader(r)
|
||||
out := []Group{}
|
||||
|
||||
var (
|
||||
s = bufio.NewScanner(r)
|
||||
out = []Group{}
|
||||
)
|
||||
// Read the file line-by-line.
|
||||
for {
|
||||
var (
|
||||
isPrefix bool
|
||||
wholeLine []byte
|
||||
err error
|
||||
)
|
||||
|
||||
for s.Scan() {
|
||||
text := s.Text()
|
||||
if text == "" {
|
||||
// Read the next line. We do so in chunks (as much as reader's
|
||||
// buffer is able to keep), check if we read enough columns
|
||||
// already on each step and store final result in wholeLine.
|
||||
for {
|
||||
var line []byte
|
||||
line, isPrefix, err = rd.ReadLine()
|
||||
|
||||
if err != nil {
|
||||
// We should return no error if EOF is reached
|
||||
// without a match.
|
||||
if err == io.EOF { //nolint:errorlint // comparison with io.EOF is legit, https://github.com/polyfloyd/go-errorlint/pull/12
|
||||
err = nil
|
||||
}
|
||||
return out, err
|
||||
}
|
||||
|
||||
// Simple common case: line is short enough to fit in a
|
||||
// single reader's buffer.
|
||||
if !isPrefix && len(wholeLine) == 0 {
|
||||
wholeLine = line
|
||||
break
|
||||
}
|
||||
|
||||
wholeLine = append(wholeLine, line...)
|
||||
|
||||
// Check if we read the whole line already.
|
||||
if !isPrefix {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// There's no spec for /etc/passwd or /etc/group, but we try to follow
|
||||
// the same rules as the glibc parser, which allows comments and blank
|
||||
// space at the beginning of a line.
|
||||
wholeLine = bytes.TrimSpace(wholeLine)
|
||||
if len(wholeLine) == 0 || wholeLine[0] == '#' {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -199,17 +236,12 @@ func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
|
|||
// root:x:0:root
|
||||
// adm:x:4:root,adm,daemon
|
||||
p := Group{}
|
||||
parseLine(text, &p.Name, &p.Pass, &p.Gid, &p.List)
|
||||
parseLine(wholeLine, &p.Name, &p.Pass, &p.Gid, &p.List)
|
||||
|
||||
if filter == nil || filter(p) {
|
||||
out = append(out, p)
|
||||
}
|
||||
}
|
||||
if err := s.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
type ExecUser struct {
|
||||
|
@ -280,7 +312,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
|
|||
|
||||
// Allow for userArg to have either "user" syntax, or optionally "user:group" syntax
|
||||
var userArg, groupArg string
|
||||
parseLine(userSpec, &userArg, &groupArg)
|
||||
parseLine([]byte(userSpec), &userArg, &groupArg)
|
||||
|
||||
// Convert userArg and groupArg to be numeric, so we don't have to execute
|
||||
// Atoi *twice* for each iteration over lines.
|
||||
|
@ -328,7 +360,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
|
|||
user.Uid = uidArg
|
||||
|
||||
// Must be inside valid uid range.
|
||||
if user.Uid < minId || user.Uid > maxId {
|
||||
if user.Uid < minID || user.Uid > maxID {
|
||||
return nil, ErrRange
|
||||
}
|
||||
|
||||
|
@ -377,7 +409,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
|
|||
user.Gid = gidArg
|
||||
|
||||
// Must be inside valid gid range.
|
||||
if user.Gid < minId || user.Gid > maxId {
|
||||
if user.Gid < minID || user.Gid > maxID {
|
||||
return nil, ErrRange
|
||||
}
|
||||
|
||||
|
@ -401,7 +433,7 @@ func GetExecUser(userSpec string, defaults *ExecUser, passwd, group io.Reader) (
|
|||
// or the given group data is nil, the id will be returned as-is
|
||||
// provided it is in the legal range.
|
||||
func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, error) {
|
||||
var groups = []Group{}
|
||||
groups := []Group{}
|
||||
if group != nil {
|
||||
var err error
|
||||
groups, err = ParseGroupFilter(group, func(g Group) bool {
|
||||
|
@ -439,7 +471,7 @@ func GetAdditionalGroups(additionalGroups []string, group io.Reader) ([]int, err
|
|||
return nil, fmt.Errorf("Unable to find group %s", ag)
|
||||
}
|
||||
// Ensure gid is inside gid range.
|
||||
if gid < minId || gid > maxId {
|
||||
if gid < minID || gid > maxID {
|
||||
return nil, ErrRange
|
||||
}
|
||||
gidMap[int(gid)] = struct{}{}
|
||||
|
@ -498,8 +530,8 @@ func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) {
|
|||
)
|
||||
|
||||
for s.Scan() {
|
||||
line := strings.TrimSpace(s.Text())
|
||||
if line == "" {
|
||||
line := bytes.TrimSpace(s.Bytes())
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -551,14 +583,14 @@ func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) {
|
|||
)
|
||||
|
||||
for s.Scan() {
|
||||
line := strings.TrimSpace(s.Text())
|
||||
if line == "" {
|
||||
line := bytes.TrimSpace(s.Bytes())
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// see: man 7 user_namespaces
|
||||
p := IDMap{}
|
||||
parseParts(strings.Fields(line), &p.ID, &p.ParentID, &p.Count)
|
||||
parseParts(bytes.Fields(line), &p.ID, &p.ParentID, &p.Count)
|
||||
|
||||
if filter == nil || filter(p) {
|
||||
out = append(out, p)
|
||||
|
|
Loading…
Reference in a new issue