update vendor
Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
This commit is contained in:
parent
7a437ada25
commit
639756e8c6
4300 changed files with 824810 additions and 9292 deletions
221
vendor/github.com/opencontainers/runc/libcontainer/specconv/example.go
generated
vendored
Normal file
221
vendor/github.com/opencontainers/runc/libcontainer/specconv/example.go
generated
vendored
Normal file
|
@ -0,0 +1,221 @@
|
|||
package specconv
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
// Example returns an example spec file, with many options set so a user can
|
||||
// see what a standard spec file looks like.
|
||||
func Example() *specs.Spec {
|
||||
return &specs.Spec{
|
||||
Version: specs.Version,
|
||||
Root: &specs.Root{
|
||||
Path: "rootfs",
|
||||
Readonly: true,
|
||||
},
|
||||
Process: &specs.Process{
|
||||
Terminal: true,
|
||||
User: specs.User{},
|
||||
Args: []string{
|
||||
"sh",
|
||||
},
|
||||
Env: []string{
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"TERM=xterm",
|
||||
},
|
||||
Cwd: "/",
|
||||
NoNewPrivileges: true,
|
||||
Capabilities: &specs.LinuxCapabilities{
|
||||
Bounding: []string{
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
},
|
||||
Permitted: []string{
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
},
|
||||
Inheritable: []string{
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
},
|
||||
Ambient: []string{
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
},
|
||||
Effective: []string{
|
||||
"CAP_AUDIT_WRITE",
|
||||
"CAP_KILL",
|
||||
"CAP_NET_BIND_SERVICE",
|
||||
},
|
||||
},
|
||||
Rlimits: []specs.POSIXRlimit{
|
||||
{
|
||||
Type: "RLIMIT_NOFILE",
|
||||
Hard: uint64(1024),
|
||||
Soft: uint64(1024),
|
||||
},
|
||||
},
|
||||
},
|
||||
Hostname: "runc",
|
||||
Mounts: []specs.Mount{
|
||||
{
|
||||
Destination: "/proc",
|
||||
Type: "proc",
|
||||
Source: "proc",
|
||||
Options: nil,
|
||||
},
|
||||
{
|
||||
Destination: "/dev",
|
||||
Type: "tmpfs",
|
||||
Source: "tmpfs",
|
||||
Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
|
||||
},
|
||||
{
|
||||
Destination: "/dev/pts",
|
||||
Type: "devpts",
|
||||
Source: "devpts",
|
||||
Options: []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"},
|
||||
},
|
||||
{
|
||||
Destination: "/dev/shm",
|
||||
Type: "tmpfs",
|
||||
Source: "shm",
|
||||
Options: []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"},
|
||||
},
|
||||
{
|
||||
Destination: "/dev/mqueue",
|
||||
Type: "mqueue",
|
||||
Source: "mqueue",
|
||||
Options: []string{"nosuid", "noexec", "nodev"},
|
||||
},
|
||||
{
|
||||
Destination: "/sys",
|
||||
Type: "sysfs",
|
||||
Source: "sysfs",
|
||||
Options: []string{"nosuid", "noexec", "nodev", "ro"},
|
||||
},
|
||||
{
|
||||
Destination: "/sys/fs/cgroup",
|
||||
Type: "cgroup",
|
||||
Source: "cgroup",
|
||||
Options: []string{"nosuid", "noexec", "nodev", "relatime", "ro"},
|
||||
},
|
||||
},
|
||||
Linux: &specs.Linux{
|
||||
MaskedPaths: []string{
|
||||
"/proc/kcore",
|
||||
"/proc/latency_stats",
|
||||
"/proc/timer_list",
|
||||
"/proc/timer_stats",
|
||||
"/proc/sched_debug",
|
||||
"/sys/firmware",
|
||||
"/proc/scsi",
|
||||
},
|
||||
ReadonlyPaths: []string{
|
||||
"/proc/asound",
|
||||
"/proc/bus",
|
||||
"/proc/fs",
|
||||
"/proc/irq",
|
||||
"/proc/sys",
|
||||
"/proc/sysrq-trigger",
|
||||
},
|
||||
Resources: &specs.LinuxResources{
|
||||
Devices: []specs.LinuxDeviceCgroup{
|
||||
{
|
||||
Allow: false,
|
||||
Access: "rwm",
|
||||
},
|
||||
},
|
||||
},
|
||||
Namespaces: []specs.LinuxNamespace{
|
||||
{
|
||||
Type: "pid",
|
||||
},
|
||||
{
|
||||
Type: "network",
|
||||
},
|
||||
{
|
||||
Type: "ipc",
|
||||
},
|
||||
{
|
||||
Type: "uts",
|
||||
},
|
||||
{
|
||||
Type: "mount",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ToRootless converts the given spec file into one that should work with
|
||||
// rootless containers, by removing incompatible options and adding others that
|
||||
// are needed.
|
||||
func ToRootless(spec *specs.Spec) {
|
||||
var namespaces []specs.LinuxNamespace
|
||||
|
||||
// Remove networkns from the spec.
|
||||
for _, ns := range spec.Linux.Namespaces {
|
||||
switch ns.Type {
|
||||
case specs.NetworkNamespace, specs.UserNamespace:
|
||||
// Do nothing.
|
||||
default:
|
||||
namespaces = append(namespaces, ns)
|
||||
}
|
||||
}
|
||||
// Add userns to the spec.
|
||||
namespaces = append(namespaces, specs.LinuxNamespace{
|
||||
Type: specs.UserNamespace,
|
||||
})
|
||||
spec.Linux.Namespaces = namespaces
|
||||
|
||||
// Add mappings for the current user.
|
||||
spec.Linux.UIDMappings = []specs.LinuxIDMapping{{
|
||||
HostID: uint32(os.Geteuid()),
|
||||
ContainerID: 0,
|
||||
Size: 1,
|
||||
}}
|
||||
spec.Linux.GIDMappings = []specs.LinuxIDMapping{{
|
||||
HostID: uint32(os.Getegid()),
|
||||
ContainerID: 0,
|
||||
Size: 1,
|
||||
}}
|
||||
|
||||
// Fix up mounts.
|
||||
var mounts []specs.Mount
|
||||
for _, mount := range spec.Mounts {
|
||||
// Ignore all mounts that are under /sys.
|
||||
if strings.HasPrefix(mount.Destination, "/sys") {
|
||||
continue
|
||||
}
|
||||
|
||||
// Remove all gid= and uid= mappings.
|
||||
var options []string
|
||||
for _, option := range mount.Options {
|
||||
if !strings.HasPrefix(option, "gid=") && !strings.HasPrefix(option, "uid=") {
|
||||
options = append(options, option)
|
||||
}
|
||||
}
|
||||
|
||||
mount.Options = options
|
||||
mounts = append(mounts, mount)
|
||||
}
|
||||
// Add the sysfs mount as an rbind.
|
||||
mounts = append(mounts, specs.Mount{
|
||||
Source: "/sys",
|
||||
Destination: "/sys",
|
||||
Type: "none",
|
||||
Options: []string{"rbind", "nosuid", "noexec", "nodev", "ro"},
|
||||
})
|
||||
spec.Mounts = mounts
|
||||
|
||||
// Remove cgroup settings.
|
||||
spec.Linux.Resources = nil
|
||||
}
|
701
vendor/github.com/opencontainers/runc/libcontainer/specconv/spec_linux.go
generated
vendored
701
vendor/github.com/opencontainers/runc/libcontainer/specconv/spec_linux.go
generated
vendored
|
@ -8,21 +8,20 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/seccomp"
|
||||
libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const wildcard = -1
|
||||
|
||||
var namespaceMapping = map[specs.NamespaceType]configs.NamespaceType{
|
||||
var namespaceMapping = map[specs.LinuxNamespaceType]configs.NamespaceType{
|
||||
specs.PIDNamespace: configs.NEWPID,
|
||||
specs.NetworkNamespace: configs.NEWNET,
|
||||
specs.MountNamespace: configs.NEWNS,
|
||||
|
@ -32,13 +31,15 @@ var namespaceMapping = map[specs.NamespaceType]configs.NamespaceType{
|
|||
}
|
||||
|
||||
var mountPropagationMapping = map[string]int{
|
||||
"rprivate": syscall.MS_PRIVATE | syscall.MS_REC,
|
||||
"private": syscall.MS_PRIVATE,
|
||||
"rslave": syscall.MS_SLAVE | syscall.MS_REC,
|
||||
"slave": syscall.MS_SLAVE,
|
||||
"rshared": syscall.MS_SHARED | syscall.MS_REC,
|
||||
"shared": syscall.MS_SHARED,
|
||||
"": syscall.MS_PRIVATE | syscall.MS_REC,
|
||||
"rprivate": unix.MS_PRIVATE | unix.MS_REC,
|
||||
"private": unix.MS_PRIVATE,
|
||||
"rslave": unix.MS_SLAVE | unix.MS_REC,
|
||||
"slave": unix.MS_SLAVE,
|
||||
"rshared": unix.MS_SHARED | unix.MS_REC,
|
||||
"shared": unix.MS_SHARED,
|
||||
"runbindable": unix.MS_UNBINDABLE | unix.MS_REC,
|
||||
"unbindable": unix.MS_UNBINDABLE,
|
||||
"": 0,
|
||||
}
|
||||
|
||||
var allowedDevices = []*configs.Device{
|
||||
|
@ -145,7 +146,9 @@ type CreateOpts struct {
|
|||
CgroupName string
|
||||
UseSystemdCgroup bool
|
||||
NoPivotRoot bool
|
||||
NoNewKeyring bool
|
||||
Spec *specs.Spec
|
||||
Rootless bool
|
||||
}
|
||||
|
||||
// CreateLibcontainerConfig creates a new libcontainer configuration from a
|
||||
|
@ -161,77 +164,110 @@ func CreateLibcontainerConfig(opts *CreateOpts) (*configs.Config, error) {
|
|||
return nil, err
|
||||
}
|
||||
spec := opts.Spec
|
||||
if spec.Root == nil {
|
||||
return nil, fmt.Errorf("Root must be specified")
|
||||
}
|
||||
rootfsPath := spec.Root.Path
|
||||
if !filepath.IsAbs(rootfsPath) {
|
||||
rootfsPath = filepath.Join(cwd, rootfsPath)
|
||||
}
|
||||
labels := []string{}
|
||||
for k, v := range spec.Annotations {
|
||||
labels = append(labels, fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
config := &configs.Config{
|
||||
Rootfs: rootfsPath,
|
||||
NoPivotRoot: opts.NoPivotRoot,
|
||||
Readonlyfs: spec.Root.Readonly,
|
||||
Hostname: spec.Hostname,
|
||||
Labels: []string{
|
||||
"bundle=" + cwd,
|
||||
},
|
||||
Rootfs: rootfsPath,
|
||||
NoPivotRoot: opts.NoPivotRoot,
|
||||
Readonlyfs: spec.Root.Readonly,
|
||||
Hostname: spec.Hostname,
|
||||
Labels: append(labels, fmt.Sprintf("bundle=%s", cwd)),
|
||||
NoNewKeyring: opts.NoNewKeyring,
|
||||
Rootless: opts.Rootless,
|
||||
}
|
||||
|
||||
exists := false
|
||||
if config.RootPropagation, exists = mountPropagationMapping[spec.Linux.RootfsPropagation]; !exists {
|
||||
return nil, fmt.Errorf("rootfsPropagation=%v is not supported", spec.Linux.RootfsPropagation)
|
||||
}
|
||||
|
||||
for _, ns := range spec.Linux.Namespaces {
|
||||
t, exists := namespaceMapping[ns.Type]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("namespace %q does not exist", ns)
|
||||
}
|
||||
config.Namespaces.Add(t, ns.Path)
|
||||
}
|
||||
if config.Namespaces.Contains(configs.NEWNET) {
|
||||
config.Networks = []*configs.Network{
|
||||
{
|
||||
Type: "loopback",
|
||||
},
|
||||
}
|
||||
}
|
||||
for _, m := range spec.Mounts {
|
||||
config.Mounts = append(config.Mounts, createLibcontainerMount(cwd, m))
|
||||
}
|
||||
if err := createDevices(spec, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := setupUserNamespace(spec, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c, err := createCgroupConfig(opts.CgroupName, opts.UseSystemdCgroup, spec)
|
||||
c, err := createCgroupConfig(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Cgroups = c
|
||||
// set extra path masking for libcontainer for the various unsafe places in proc
|
||||
config.MaskPaths = spec.Linux.MaskedPaths
|
||||
config.ReadonlyPaths = spec.Linux.ReadonlyPaths
|
||||
if spec.Linux.Seccomp != nil {
|
||||
seccomp, err := setupSeccomp(spec.Linux.Seccomp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// set linux-specific config
|
||||
if spec.Linux != nil {
|
||||
if config.RootPropagation, exists = mountPropagationMapping[spec.Linux.RootfsPropagation]; !exists {
|
||||
return nil, fmt.Errorf("rootfsPropagation=%v is not supported", spec.Linux.RootfsPropagation)
|
||||
}
|
||||
if config.NoPivotRoot && (config.RootPropagation&unix.MS_PRIVATE != 0) {
|
||||
return nil, fmt.Errorf("rootfsPropagation of [r]private is not safe without pivot_root")
|
||||
}
|
||||
|
||||
for _, ns := range spec.Linux.Namespaces {
|
||||
t, exists := namespaceMapping[ns.Type]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("namespace %q does not exist", ns)
|
||||
}
|
||||
if config.Namespaces.Contains(t) {
|
||||
return nil, fmt.Errorf("malformed spec file: duplicated ns %q", ns)
|
||||
}
|
||||
config.Namespaces.Add(t, ns.Path)
|
||||
}
|
||||
if config.Namespaces.Contains(configs.NEWNET) {
|
||||
config.Networks = []*configs.Network{
|
||||
{
|
||||
Type: "loopback",
|
||||
},
|
||||
}
|
||||
}
|
||||
if config.Namespaces.Contains(configs.NEWUSER) {
|
||||
if err := setupUserNamespace(spec, config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
config.MaskPaths = spec.Linux.MaskedPaths
|
||||
config.ReadonlyPaths = spec.Linux.ReadonlyPaths
|
||||
config.MountLabel = spec.Linux.MountLabel
|
||||
config.Sysctl = spec.Linux.Sysctl
|
||||
if spec.Linux.Seccomp != nil {
|
||||
seccomp, err := setupSeccomp(spec.Linux.Seccomp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Seccomp = seccomp
|
||||
}
|
||||
config.Seccomp = seccomp
|
||||
}
|
||||
config.Sysctl = spec.Linux.Sysctl
|
||||
if oomScoreAdj := spec.Linux.Resources.OOMScoreAdj; oomScoreAdj != nil {
|
||||
config.OomScoreAdj = *oomScoreAdj
|
||||
if spec.Process.SelinuxLabel != "" {
|
||||
config.ProcessLabel = spec.Process.SelinuxLabel
|
||||
}
|
||||
for _, g := range spec.Process.User.AdditionalGids {
|
||||
config.AdditionalGroups = append(config.AdditionalGroups, strconv.FormatUint(uint64(g), 10))
|
||||
if spec.Process != nil && spec.Process.OOMScoreAdj != nil {
|
||||
config.OomScoreAdj = *spec.Process.OOMScoreAdj
|
||||
}
|
||||
if spec.Process.Capabilities != nil {
|
||||
config.Capabilities = &configs.Capabilities{
|
||||
Bounding: spec.Process.Capabilities.Bounding,
|
||||
Effective: spec.Process.Capabilities.Effective,
|
||||
Permitted: spec.Process.Capabilities.Permitted,
|
||||
Inheritable: spec.Process.Capabilities.Inheritable,
|
||||
Ambient: spec.Process.Capabilities.Ambient,
|
||||
}
|
||||
}
|
||||
createHooks(spec, config)
|
||||
config.Version = specs.Version
|
||||
if spec.Linux.IntelRdt != nil {
|
||||
config.IntelRdt = &configs.IntelRdt{}
|
||||
if spec.Linux.IntelRdt.L3CacheSchema != "" {
|
||||
config.IntelRdt.L3CacheSchema = spec.Linux.IntelRdt.L3CacheSchema
|
||||
}
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func createLibcontainerMount(cwd string, m specs.Mount) *configs.Mount {
|
||||
flags, pgflags, data := parseMountOptions(m.Options)
|
||||
flags, pgflags, data, ext := parseMountOptions(m.Options)
|
||||
source := m.Source
|
||||
if m.Type == "bind" {
|
||||
if !filepath.IsAbs(source) {
|
||||
|
@ -245,23 +281,27 @@ func createLibcontainerMount(cwd string, m specs.Mount) *configs.Mount {
|
|||
Data: data,
|
||||
Flags: flags,
|
||||
PropagationFlags: pgflags,
|
||||
Extensions: ext,
|
||||
}
|
||||
}
|
||||
|
||||
func createCgroupConfig(name string, useSystemdCgroup bool, spec *specs.Spec) (*configs.Cgroup, error) {
|
||||
func createCgroupConfig(opts *CreateOpts) (*configs.Cgroup, error) {
|
||||
var (
|
||||
err error
|
||||
myCgroupPath string
|
||||
|
||||
spec = opts.Spec
|
||||
useSystemdCgroup = opts.UseSystemdCgroup
|
||||
name = opts.CgroupName
|
||||
)
|
||||
|
||||
c := &configs.Cgroup{
|
||||
Resources: &configs.Resources{},
|
||||
}
|
||||
|
||||
if spec.Linux.CgroupsPath != nil {
|
||||
myCgroupPath = libcontainerUtils.CleanPath(*spec.Linux.CgroupsPath)
|
||||
if spec.Linux != nil && spec.Linux.CgroupsPath != "" {
|
||||
myCgroupPath = libcontainerUtils.CleanPath(spec.Linux.CgroupsPath)
|
||||
if useSystemdCgroup {
|
||||
myCgroupPath = *spec.Linux.CgroupsPath
|
||||
myCgroupPath = spec.Linux.CgroupsPath
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,162 +323,177 @@ func createCgroupConfig(name string, useSystemdCgroup bool, spec *specs.Spec) (*
|
|||
}
|
||||
} else {
|
||||
if myCgroupPath == "" {
|
||||
myCgroupPath, err = cgroups.GetThisCgroupDir("devices")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
myCgroupPath = filepath.Join(myCgroupPath, name)
|
||||
c.Name = name
|
||||
}
|
||||
c.Path = myCgroupPath
|
||||
}
|
||||
|
||||
c.Resources.AllowedDevices = allowedDevices
|
||||
r := spec.Linux.Resources
|
||||
if r == nil {
|
||||
return c, nil
|
||||
// In rootless containers, any attempt to make cgroup changes will fail.
|
||||
// libcontainer will validate this and we shouldn't add any cgroup options
|
||||
// the user didn't specify.
|
||||
if !opts.Rootless {
|
||||
c.Resources.AllowedDevices = allowedDevices
|
||||
}
|
||||
for i, d := range spec.Linux.Resources.Devices {
|
||||
var (
|
||||
t = "a"
|
||||
major = int64(-1)
|
||||
minor = int64(-1)
|
||||
)
|
||||
if d.Type != nil {
|
||||
t = *d.Type
|
||||
if spec.Linux != nil {
|
||||
r := spec.Linux.Resources
|
||||
if r == nil {
|
||||
return c, nil
|
||||
}
|
||||
if d.Major != nil {
|
||||
major = *d.Major
|
||||
for i, d := range spec.Linux.Resources.Devices {
|
||||
var (
|
||||
t = "a"
|
||||
major = int64(-1)
|
||||
minor = int64(-1)
|
||||
)
|
||||
if d.Type != "" {
|
||||
t = d.Type
|
||||
}
|
||||
if d.Major != nil {
|
||||
major = *d.Major
|
||||
}
|
||||
if d.Minor != nil {
|
||||
minor = *d.Minor
|
||||
}
|
||||
if d.Access == "" {
|
||||
return nil, fmt.Errorf("device access at %d field cannot be empty", i)
|
||||
}
|
||||
dt, err := stringToCgroupDeviceRune(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dd := &configs.Device{
|
||||
Type: dt,
|
||||
Major: major,
|
||||
Minor: minor,
|
||||
Permissions: d.Access,
|
||||
Allow: d.Allow,
|
||||
}
|
||||
c.Resources.Devices = append(c.Resources.Devices, dd)
|
||||
}
|
||||
if d.Minor != nil {
|
||||
minor = *d.Minor
|
||||
}
|
||||
if d.Access == nil || *d.Access == "" {
|
||||
return nil, fmt.Errorf("device access at %d field cannot be empty", i)
|
||||
}
|
||||
dt, err := stringToDeviceRune(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dd := &configs.Device{
|
||||
Type: dt,
|
||||
Major: major,
|
||||
Minor: minor,
|
||||
Permissions: *d.Access,
|
||||
Allow: d.Allow,
|
||||
}
|
||||
c.Resources.Devices = append(c.Resources.Devices, dd)
|
||||
}
|
||||
// append the default allowed devices to the end of the list
|
||||
c.Resources.Devices = append(c.Resources.Devices, allowedDevices...)
|
||||
if r.Memory != nil {
|
||||
if r.Memory.Limit != nil {
|
||||
c.Resources.Memory = int64(*r.Memory.Limit)
|
||||
}
|
||||
if r.Memory.Reservation != nil {
|
||||
c.Resources.MemoryReservation = int64(*r.Memory.Reservation)
|
||||
}
|
||||
if r.Memory.Swap != nil {
|
||||
c.Resources.MemorySwap = int64(*r.Memory.Swap)
|
||||
}
|
||||
if r.Memory.Kernel != nil {
|
||||
c.Resources.KernelMemory = int64(*r.Memory.Kernel)
|
||||
}
|
||||
if r.Memory.KernelTCP != nil {
|
||||
c.Resources.KernelMemoryTCP = int64(*r.Memory.KernelTCP)
|
||||
}
|
||||
if r.Memory.Swappiness != nil {
|
||||
swappiness := int64(*r.Memory.Swappiness)
|
||||
c.Resources.MemorySwappiness = &swappiness
|
||||
}
|
||||
}
|
||||
if r.CPU != nil {
|
||||
if r.CPU.Shares != nil {
|
||||
c.Resources.CpuShares = int64(*r.CPU.Shares)
|
||||
}
|
||||
if r.CPU.Quota != nil {
|
||||
c.Resources.CpuQuota = int64(*r.CPU.Quota)
|
||||
}
|
||||
if r.CPU.Period != nil {
|
||||
c.Resources.CpuPeriod = int64(*r.CPU.Period)
|
||||
}
|
||||
if r.CPU.RealtimeRuntime != nil {
|
||||
c.Resources.CpuRtRuntime = int64(*r.CPU.RealtimeRuntime)
|
||||
}
|
||||
if r.CPU.RealtimePeriod != nil {
|
||||
c.Resources.CpuRtPeriod = int64(*r.CPU.RealtimePeriod)
|
||||
}
|
||||
if r.CPU.Cpus != nil {
|
||||
c.Resources.CpusetCpus = *r.CPU.Cpus
|
||||
}
|
||||
if r.CPU.Mems != nil {
|
||||
c.Resources.CpusetMems = *r.CPU.Mems
|
||||
}
|
||||
}
|
||||
if r.Pids != nil {
|
||||
c.Resources.PidsLimit = *r.Pids.Limit
|
||||
}
|
||||
if r.BlockIO != nil {
|
||||
if r.BlockIO.Weight != nil {
|
||||
c.Resources.BlkioWeight = *r.BlockIO.Weight
|
||||
}
|
||||
if r.BlockIO.LeafWeight != nil {
|
||||
c.Resources.BlkioLeafWeight = *r.BlockIO.LeafWeight
|
||||
}
|
||||
if r.BlockIO.WeightDevice != nil {
|
||||
for _, wd := range r.BlockIO.WeightDevice {
|
||||
weightDevice := configs.NewWeightDevice(wd.Major, wd.Minor, *wd.Weight, *wd.LeafWeight)
|
||||
c.Resources.BlkioWeightDevice = append(c.Resources.BlkioWeightDevice, weightDevice)
|
||||
if r.Memory != nil {
|
||||
if r.Memory.Limit != nil {
|
||||
c.Resources.Memory = *r.Memory.Limit
|
||||
}
|
||||
if r.Memory.Reservation != nil {
|
||||
c.Resources.MemoryReservation = *r.Memory.Reservation
|
||||
}
|
||||
if r.Memory.Swap != nil {
|
||||
c.Resources.MemorySwap = *r.Memory.Swap
|
||||
}
|
||||
if r.Memory.Kernel != nil {
|
||||
c.Resources.KernelMemory = *r.Memory.Kernel
|
||||
}
|
||||
if r.Memory.KernelTCP != nil {
|
||||
c.Resources.KernelMemoryTCP = *r.Memory.KernelTCP
|
||||
}
|
||||
if r.Memory.Swappiness != nil {
|
||||
c.Resources.MemorySwappiness = r.Memory.Swappiness
|
||||
}
|
||||
if r.Memory.DisableOOMKiller != nil {
|
||||
c.Resources.OomKillDisable = *r.Memory.DisableOOMKiller
|
||||
}
|
||||
}
|
||||
if r.BlockIO.ThrottleReadBpsDevice != nil {
|
||||
for _, td := range r.BlockIO.ThrottleReadBpsDevice {
|
||||
throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, *td.Rate)
|
||||
c.Resources.BlkioThrottleReadBpsDevice = append(c.Resources.BlkioThrottleReadBpsDevice, throttleDevice)
|
||||
if r.CPU != nil {
|
||||
if r.CPU.Shares != nil {
|
||||
c.Resources.CpuShares = *r.CPU.Shares
|
||||
}
|
||||
if r.CPU.Quota != nil {
|
||||
c.Resources.CpuQuota = *r.CPU.Quota
|
||||
}
|
||||
if r.CPU.Period != nil {
|
||||
c.Resources.CpuPeriod = *r.CPU.Period
|
||||
}
|
||||
if r.CPU.RealtimeRuntime != nil {
|
||||
c.Resources.CpuRtRuntime = *r.CPU.RealtimeRuntime
|
||||
}
|
||||
if r.CPU.RealtimePeriod != nil {
|
||||
c.Resources.CpuRtPeriod = *r.CPU.RealtimePeriod
|
||||
}
|
||||
if r.CPU.Cpus != "" {
|
||||
c.Resources.CpusetCpus = r.CPU.Cpus
|
||||
}
|
||||
if r.CPU.Mems != "" {
|
||||
c.Resources.CpusetMems = r.CPU.Mems
|
||||
}
|
||||
}
|
||||
if r.BlockIO.ThrottleWriteBpsDevice != nil {
|
||||
for _, td := range r.BlockIO.ThrottleWriteBpsDevice {
|
||||
throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, *td.Rate)
|
||||
c.Resources.BlkioThrottleWriteBpsDevice = append(c.Resources.BlkioThrottleWriteBpsDevice, throttleDevice)
|
||||
if r.Pids != nil {
|
||||
c.Resources.PidsLimit = r.Pids.Limit
|
||||
}
|
||||
if r.BlockIO != nil {
|
||||
if r.BlockIO.Weight != nil {
|
||||
c.Resources.BlkioWeight = *r.BlockIO.Weight
|
||||
}
|
||||
if r.BlockIO.LeafWeight != nil {
|
||||
c.Resources.BlkioLeafWeight = *r.BlockIO.LeafWeight
|
||||
}
|
||||
if r.BlockIO.WeightDevice != nil {
|
||||
for _, wd := range r.BlockIO.WeightDevice {
|
||||
var weight, leafWeight uint16
|
||||
if wd.Weight != nil {
|
||||
weight = *wd.Weight
|
||||
}
|
||||
if wd.LeafWeight != nil {
|
||||
leafWeight = *wd.LeafWeight
|
||||
}
|
||||
weightDevice := configs.NewWeightDevice(wd.Major, wd.Minor, weight, leafWeight)
|
||||
c.Resources.BlkioWeightDevice = append(c.Resources.BlkioWeightDevice, weightDevice)
|
||||
}
|
||||
}
|
||||
if r.BlockIO.ThrottleReadBpsDevice != nil {
|
||||
for _, td := range r.BlockIO.ThrottleReadBpsDevice {
|
||||
rate := td.Rate
|
||||
throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, rate)
|
||||
c.Resources.BlkioThrottleReadBpsDevice = append(c.Resources.BlkioThrottleReadBpsDevice, throttleDevice)
|
||||
}
|
||||
}
|
||||
if r.BlockIO.ThrottleWriteBpsDevice != nil {
|
||||
for _, td := range r.BlockIO.ThrottleWriteBpsDevice {
|
||||
rate := td.Rate
|
||||
throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, rate)
|
||||
c.Resources.BlkioThrottleWriteBpsDevice = append(c.Resources.BlkioThrottleWriteBpsDevice, throttleDevice)
|
||||
}
|
||||
}
|
||||
if r.BlockIO.ThrottleReadIOPSDevice != nil {
|
||||
for _, td := range r.BlockIO.ThrottleReadIOPSDevice {
|
||||
rate := td.Rate
|
||||
throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, rate)
|
||||
c.Resources.BlkioThrottleReadIOPSDevice = append(c.Resources.BlkioThrottleReadIOPSDevice, throttleDevice)
|
||||
}
|
||||
}
|
||||
if r.BlockIO.ThrottleWriteIOPSDevice != nil {
|
||||
for _, td := range r.BlockIO.ThrottleWriteIOPSDevice {
|
||||
rate := td.Rate
|
||||
throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, rate)
|
||||
c.Resources.BlkioThrottleWriteIOPSDevice = append(c.Resources.BlkioThrottleWriteIOPSDevice, throttleDevice)
|
||||
}
|
||||
}
|
||||
}
|
||||
if r.BlockIO.ThrottleReadIOPSDevice != nil {
|
||||
for _, td := range r.BlockIO.ThrottleReadIOPSDevice {
|
||||
throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, *td.Rate)
|
||||
c.Resources.BlkioThrottleReadIOPSDevice = append(c.Resources.BlkioThrottleReadIOPSDevice, throttleDevice)
|
||||
}
|
||||
}
|
||||
if r.BlockIO.ThrottleWriteIOPSDevice != nil {
|
||||
for _, td := range r.BlockIO.ThrottleWriteIOPSDevice {
|
||||
throttleDevice := configs.NewThrottleDevice(td.Major, td.Minor, *td.Rate)
|
||||
c.Resources.BlkioThrottleWriteIOPSDevice = append(c.Resources.BlkioThrottleWriteIOPSDevice, throttleDevice)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, l := range r.HugepageLimits {
|
||||
c.Resources.HugetlbLimit = append(c.Resources.HugetlbLimit, &configs.HugepageLimit{
|
||||
Pagesize: *l.Pagesize,
|
||||
Limit: *l.Limit,
|
||||
})
|
||||
}
|
||||
if r.DisableOOMKiller != nil {
|
||||
c.Resources.OomKillDisable = *r.DisableOOMKiller
|
||||
}
|
||||
if r.Network != nil {
|
||||
if r.Network.ClassID != nil {
|
||||
c.Resources.NetClsClassid = string(*r.Network.ClassID)
|
||||
}
|
||||
for _, m := range r.Network.Priorities {
|
||||
c.Resources.NetPrioIfpriomap = append(c.Resources.NetPrioIfpriomap, &configs.IfPrioMap{
|
||||
Interface: m.Name,
|
||||
Priority: int64(m.Priority),
|
||||
for _, l := range r.HugepageLimits {
|
||||
c.Resources.HugetlbLimit = append(c.Resources.HugetlbLimit, &configs.HugepageLimit{
|
||||
Pagesize: l.Pagesize,
|
||||
Limit: l.Limit,
|
||||
})
|
||||
}
|
||||
if r.Network != nil {
|
||||
if r.Network.ClassID != nil {
|
||||
c.Resources.NetClsClassid = *r.Network.ClassID
|
||||
}
|
||||
for _, m := range r.Network.Priorities {
|
||||
c.Resources.NetPrioIfpriomap = append(c.Resources.NetPrioIfpriomap, &configs.IfPrioMap{
|
||||
Interface: m.Name,
|
||||
Priority: int64(m.Priority),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if !opts.Rootless {
|
||||
// append the default allowed devices to the end of the list
|
||||
c.Resources.Devices = append(c.Resources.Devices, allowedDevices...)
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func stringToDeviceRune(s string) (rune, error) {
|
||||
func stringToCgroupDeviceRune(s string) (rune, error) {
|
||||
switch s {
|
||||
case "a":
|
||||
return 'a', nil
|
||||
|
@ -446,6 +501,21 @@ func stringToDeviceRune(s string) (rune, error) {
|
|||
return 'b', nil
|
||||
case "c":
|
||||
return 'c', nil
|
||||
default:
|
||||
return 0, fmt.Errorf("invalid cgroup device type %q", s)
|
||||
}
|
||||
}
|
||||
|
||||
func stringToDeviceRune(s string) (rune, error) {
|
||||
switch s {
|
||||
case "p":
|
||||
return 'p', nil
|
||||
case "u":
|
||||
return 'u', nil
|
||||
case "b":
|
||||
return 'b', nil
|
||||
case "c":
|
||||
return 'c', nil
|
||||
default:
|
||||
return 0, fmt.Errorf("invalid device type %q", s)
|
||||
}
|
||||
|
@ -510,58 +580,60 @@ func createDevices(spec *specs.Spec, config *configs.Config) error {
|
|||
},
|
||||
}
|
||||
// merge in additional devices from the spec
|
||||
for _, d := range spec.Linux.Devices {
|
||||
var uid, gid uint32
|
||||
if d.UID != nil {
|
||||
uid = *d.UID
|
||||
if spec.Linux != nil {
|
||||
for _, d := range spec.Linux.Devices {
|
||||
var uid, gid uint32
|
||||
var filemode os.FileMode = 0666
|
||||
|
||||
if d.UID != nil {
|
||||
uid = *d.UID
|
||||
}
|
||||
if d.GID != nil {
|
||||
gid = *d.GID
|
||||
}
|
||||
dt, err := stringToDeviceRune(d.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.FileMode != nil {
|
||||
filemode = *d.FileMode
|
||||
}
|
||||
device := &configs.Device{
|
||||
Type: dt,
|
||||
Path: d.Path,
|
||||
Major: d.Major,
|
||||
Minor: d.Minor,
|
||||
FileMode: filemode,
|
||||
Uid: uid,
|
||||
Gid: gid,
|
||||
}
|
||||
config.Devices = append(config.Devices, device)
|
||||
}
|
||||
if d.GID != nil {
|
||||
gid = *d.GID
|
||||
}
|
||||
dt, err := stringToDeviceRune(d.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
device := &configs.Device{
|
||||
Type: dt,
|
||||
Path: d.Path,
|
||||
Major: d.Major,
|
||||
Minor: d.Minor,
|
||||
FileMode: *d.FileMode,
|
||||
Uid: uid,
|
||||
Gid: gid,
|
||||
}
|
||||
config.Devices = append(config.Devices, device)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupUserNamespace(spec *specs.Spec, config *configs.Config) error {
|
||||
if len(spec.Linux.UIDMappings) == 0 {
|
||||
return nil
|
||||
}
|
||||
// do not override the specified user namespace path
|
||||
if config.Namespaces.PathOf(configs.NEWUSER) == "" {
|
||||
config.Namespaces.Add(configs.NEWUSER, "")
|
||||
}
|
||||
create := func(m specs.IDMapping) configs.IDMap {
|
||||
create := func(m specs.LinuxIDMapping) configs.IDMap {
|
||||
return configs.IDMap{
|
||||
HostID: int(m.HostID),
|
||||
ContainerID: int(m.ContainerID),
|
||||
Size: int(m.Size),
|
||||
}
|
||||
}
|
||||
for _, m := range spec.Linux.UIDMappings {
|
||||
config.UidMappings = append(config.UidMappings, create(m))
|
||||
if spec.Linux != nil {
|
||||
for _, m := range spec.Linux.UIDMappings {
|
||||
config.UidMappings = append(config.UidMappings, create(m))
|
||||
}
|
||||
for _, m := range spec.Linux.GIDMappings {
|
||||
config.GidMappings = append(config.GidMappings, create(m))
|
||||
}
|
||||
}
|
||||
for _, m := range spec.Linux.GIDMappings {
|
||||
config.GidMappings = append(config.GidMappings, create(m))
|
||||
}
|
||||
rootUID, err := config.HostUID()
|
||||
rootUID, err := config.HostRootUID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rootGID, err := config.HostGID()
|
||||
rootGID, err := config.HostRootGID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -574,54 +646,66 @@ func setupUserNamespace(spec *specs.Spec, config *configs.Config) error {
|
|||
|
||||
// parseMountOptions parses the string and returns the flags, propagation
|
||||
// flags and any mount data that it contains.
|
||||
func parseMountOptions(options []string) (int, []int, string) {
|
||||
func parseMountOptions(options []string) (int, []int, string, int) {
|
||||
var (
|
||||
flag int
|
||||
pgflag []int
|
||||
data []string
|
||||
flag int
|
||||
pgflag []int
|
||||
data []string
|
||||
extFlags int
|
||||
)
|
||||
flags := map[string]struct {
|
||||
clear bool
|
||||
flag int
|
||||
}{
|
||||
"async": {true, syscall.MS_SYNCHRONOUS},
|
||||
"atime": {true, syscall.MS_NOATIME},
|
||||
"bind": {false, syscall.MS_BIND},
|
||||
"acl": {false, unix.MS_POSIXACL},
|
||||
"async": {true, unix.MS_SYNCHRONOUS},
|
||||
"atime": {true, unix.MS_NOATIME},
|
||||
"bind": {false, unix.MS_BIND},
|
||||
"defaults": {false, 0},
|
||||
"dev": {true, syscall.MS_NODEV},
|
||||
"diratime": {true, syscall.MS_NODIRATIME},
|
||||
"dirsync": {false, syscall.MS_DIRSYNC},
|
||||
"exec": {true, syscall.MS_NOEXEC},
|
||||
"mand": {false, syscall.MS_MANDLOCK},
|
||||
"noatime": {false, syscall.MS_NOATIME},
|
||||
"nodev": {false, syscall.MS_NODEV},
|
||||
"nodiratime": {false, syscall.MS_NODIRATIME},
|
||||
"noexec": {false, syscall.MS_NOEXEC},
|
||||
"nomand": {true, syscall.MS_MANDLOCK},
|
||||
"norelatime": {true, syscall.MS_RELATIME},
|
||||
"nostrictatime": {true, syscall.MS_STRICTATIME},
|
||||
"nosuid": {false, syscall.MS_NOSUID},
|
||||
"rbind": {false, syscall.MS_BIND | syscall.MS_REC},
|
||||
"relatime": {false, syscall.MS_RELATIME},
|
||||
"remount": {false, syscall.MS_REMOUNT},
|
||||
"ro": {false, syscall.MS_RDONLY},
|
||||
"rw": {true, syscall.MS_RDONLY},
|
||||
"strictatime": {false, syscall.MS_STRICTATIME},
|
||||
"suid": {true, syscall.MS_NOSUID},
|
||||
"sync": {false, syscall.MS_SYNCHRONOUS},
|
||||
"dev": {true, unix.MS_NODEV},
|
||||
"diratime": {true, unix.MS_NODIRATIME},
|
||||
"dirsync": {false, unix.MS_DIRSYNC},
|
||||
"exec": {true, unix.MS_NOEXEC},
|
||||
"iversion": {false, unix.MS_I_VERSION},
|
||||
"lazytime": {false, unix.MS_LAZYTIME},
|
||||
"loud": {true, unix.MS_SILENT},
|
||||
"mand": {false, unix.MS_MANDLOCK},
|
||||
"noacl": {true, unix.MS_POSIXACL},
|
||||
"noatime": {false, unix.MS_NOATIME},
|
||||
"nodev": {false, unix.MS_NODEV},
|
||||
"nodiratime": {false, unix.MS_NODIRATIME},
|
||||
"noexec": {false, unix.MS_NOEXEC},
|
||||
"noiversion": {true, unix.MS_I_VERSION},
|
||||
"nolazytime": {true, unix.MS_LAZYTIME},
|
||||
"nomand": {true, unix.MS_MANDLOCK},
|
||||
"norelatime": {true, unix.MS_RELATIME},
|
||||
"nostrictatime": {true, unix.MS_STRICTATIME},
|
||||
"nosuid": {false, unix.MS_NOSUID},
|
||||
"rbind": {false, unix.MS_BIND | unix.MS_REC},
|
||||
"relatime": {false, unix.MS_RELATIME},
|
||||
"remount": {false, unix.MS_REMOUNT},
|
||||
"ro": {false, unix.MS_RDONLY},
|
||||
"rw": {true, unix.MS_RDONLY},
|
||||
"silent": {false, unix.MS_SILENT},
|
||||
"strictatime": {false, unix.MS_STRICTATIME},
|
||||
"suid": {true, unix.MS_NOSUID},
|
||||
"sync": {false, unix.MS_SYNCHRONOUS},
|
||||
}
|
||||
propagationFlags := map[string]struct {
|
||||
propagationFlags := map[string]int{
|
||||
"private": unix.MS_PRIVATE,
|
||||
"shared": unix.MS_SHARED,
|
||||
"slave": unix.MS_SLAVE,
|
||||
"unbindable": unix.MS_UNBINDABLE,
|
||||
"rprivate": unix.MS_PRIVATE | unix.MS_REC,
|
||||
"rshared": unix.MS_SHARED | unix.MS_REC,
|
||||
"rslave": unix.MS_SLAVE | unix.MS_REC,
|
||||
"runbindable": unix.MS_UNBINDABLE | unix.MS_REC,
|
||||
}
|
||||
extensionFlags := map[string]struct {
|
||||
clear bool
|
||||
flag int
|
||||
}{
|
||||
"private": {false, syscall.MS_PRIVATE},
|
||||
"shared": {false, syscall.MS_SHARED},
|
||||
"slave": {false, syscall.MS_SLAVE},
|
||||
"unbindable": {false, syscall.MS_UNBINDABLE},
|
||||
"rprivate": {false, syscall.MS_PRIVATE | syscall.MS_REC},
|
||||
"rshared": {false, syscall.MS_SHARED | syscall.MS_REC},
|
||||
"rslave": {false, syscall.MS_SLAVE | syscall.MS_REC},
|
||||
"runbindable": {false, syscall.MS_UNBINDABLE | syscall.MS_REC},
|
||||
"tmpcopyup": {false, configs.EXT_COPYUP},
|
||||
}
|
||||
for _, o := range options {
|
||||
// If the option does not exist in the flags table or the flag
|
||||
|
@ -633,16 +717,22 @@ func parseMountOptions(options []string) (int, []int, string) {
|
|||
} else {
|
||||
flag |= f.flag
|
||||
}
|
||||
} else if f, exists := propagationFlags[o]; exists && f.flag != 0 {
|
||||
pgflag = append(pgflag, f.flag)
|
||||
} else if f, exists := propagationFlags[o]; exists && f != 0 {
|
||||
pgflag = append(pgflag, f)
|
||||
} else if f, exists := extensionFlags[o]; exists && f.flag != 0 {
|
||||
if f.clear {
|
||||
extFlags &= ^f.flag
|
||||
} else {
|
||||
extFlags |= f.flag
|
||||
}
|
||||
} else {
|
||||
data = append(data, o)
|
||||
}
|
||||
}
|
||||
return flag, pgflag, strings.Join(data, ",")
|
||||
return flag, pgflag, strings.Join(data, ","), extFlags
|
||||
}
|
||||
|
||||
func setupSeccomp(config *specs.Seccomp) (*configs.Seccomp, error) {
|
||||
func setupSeccomp(config *specs.LinuxSeccomp) (*configs.Seccomp, error) {
|
||||
if config == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -680,30 +770,30 @@ func setupSeccomp(config *specs.Seccomp) (*configs.Seccomp, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
newCall := configs.Syscall{
|
||||
Name: call.Name,
|
||||
Action: newAction,
|
||||
Args: []*configs.Arg{},
|
||||
}
|
||||
|
||||
// Loop through all the arguments of the syscall and convert them
|
||||
for _, arg := range call.Args {
|
||||
newOp, err := seccomp.ConvertStringToOperator(string(arg.Op))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
for _, name := range call.Names {
|
||||
newCall := configs.Syscall{
|
||||
Name: name,
|
||||
Action: newAction,
|
||||
Args: []*configs.Arg{},
|
||||
}
|
||||
// Loop through all the arguments of the syscall and convert them
|
||||
for _, arg := range call.Args {
|
||||
newOp, err := seccomp.ConvertStringToOperator(string(arg.Op))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newArg := configs.Arg{
|
||||
Index: arg.Index,
|
||||
Value: arg.Value,
|
||||
ValueTwo: arg.ValueTwo,
|
||||
Op: newOp,
|
||||
newArg := configs.Arg{
|
||||
Index: arg.Index,
|
||||
Value: arg.Value,
|
||||
ValueTwo: arg.ValueTwo,
|
||||
Op: newOp,
|
||||
}
|
||||
|
||||
newCall.Args = append(newCall.Args, &newArg)
|
||||
}
|
||||
|
||||
newCall.Args = append(newCall.Args, &newArg)
|
||||
newConfig.Syscalls = append(newConfig.Syscalls, &newCall)
|
||||
}
|
||||
|
||||
newConfig.Syscalls = append(newConfig.Syscalls, &newCall)
|
||||
}
|
||||
|
||||
return newConfig, nil
|
||||
|
@ -711,17 +801,20 @@ func setupSeccomp(config *specs.Seccomp) (*configs.Seccomp, error) {
|
|||
|
||||
func createHooks(rspec *specs.Spec, config *configs.Config) {
|
||||
config.Hooks = &configs.Hooks{}
|
||||
for _, h := range rspec.Hooks.Prestart {
|
||||
cmd := createCommandHook(h)
|
||||
config.Hooks.Prestart = append(config.Hooks.Prestart, configs.NewCommandHook(cmd))
|
||||
}
|
||||
for _, h := range rspec.Hooks.Poststart {
|
||||
cmd := createCommandHook(h)
|
||||
config.Hooks.Poststart = append(config.Hooks.Poststart, configs.NewCommandHook(cmd))
|
||||
}
|
||||
for _, h := range rspec.Hooks.Poststop {
|
||||
cmd := createCommandHook(h)
|
||||
config.Hooks.Poststop = append(config.Hooks.Poststop, configs.NewCommandHook(cmd))
|
||||
if rspec.Hooks != nil {
|
||||
|
||||
for _, h := range rspec.Hooks.Prestart {
|
||||
cmd := createCommandHook(h)
|
||||
config.Hooks.Prestart = append(config.Hooks.Prestart, configs.NewCommandHook(cmd))
|
||||
}
|
||||
for _, h := range rspec.Hooks.Poststart {
|
||||
cmd := createCommandHook(h)
|
||||
config.Hooks.Poststart = append(config.Hooks.Poststart, configs.NewCommandHook(cmd))
|
||||
}
|
||||
for _, h := range rspec.Hooks.Poststop {
|
||||
cmd := createCommandHook(h)
|
||||
config.Hooks.Poststop = append(config.Hooks.Poststop, configs.NewCommandHook(cmd))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
445
vendor/github.com/opencontainers/runc/libcontainer/specconv/spec_linux_test.go
generated
vendored
Normal file
445
vendor/github.com/opencontainers/runc/libcontainer/specconv/spec_linux_test.go
generated
vendored
Normal file
|
@ -0,0 +1,445 @@
|
|||
// +build linux
|
||||
|
||||
package specconv
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/configs/validate"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
func TestCreateCommandHookTimeout(t *testing.T) {
|
||||
timeout := 3600
|
||||
hook := specs.Hook{
|
||||
Path: "/some/hook/path",
|
||||
Args: []string{"--some", "thing"},
|
||||
Env: []string{"SOME=value"},
|
||||
Timeout: &timeout,
|
||||
}
|
||||
command := createCommandHook(hook)
|
||||
timeoutStr := command.Timeout.String()
|
||||
if timeoutStr != "1h0m0s" {
|
||||
t.Errorf("Expected the Timeout to be 1h0m0s, got: %s", timeoutStr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateHooks(t *testing.T) {
|
||||
rspec := &specs.Spec{
|
||||
Hooks: &specs.Hooks{
|
||||
Prestart: []specs.Hook{
|
||||
{
|
||||
Path: "/some/hook/path",
|
||||
},
|
||||
{
|
||||
Path: "/some/hook2/path",
|
||||
Args: []string{"--some", "thing"},
|
||||
},
|
||||
},
|
||||
Poststart: []specs.Hook{
|
||||
{
|
||||
Path: "/some/hook/path",
|
||||
Args: []string{"--some", "thing"},
|
||||
Env: []string{"SOME=value"},
|
||||
},
|
||||
{
|
||||
Path: "/some/hook2/path",
|
||||
},
|
||||
{
|
||||
Path: "/some/hook3/path",
|
||||
},
|
||||
},
|
||||
Poststop: []specs.Hook{
|
||||
{
|
||||
Path: "/some/hook/path",
|
||||
Args: []string{"--some", "thing"},
|
||||
Env: []string{"SOME=value"},
|
||||
},
|
||||
{
|
||||
Path: "/some/hook2/path",
|
||||
},
|
||||
{
|
||||
Path: "/some/hook3/path",
|
||||
},
|
||||
{
|
||||
Path: "/some/hook4/path",
|
||||
Args: []string{"--some", "thing"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
conf := &configs.Config{}
|
||||
createHooks(rspec, conf)
|
||||
|
||||
prestart := conf.Hooks.Prestart
|
||||
|
||||
if len(prestart) != 2 {
|
||||
t.Error("Expected 2 Prestart hooks")
|
||||
}
|
||||
|
||||
poststart := conf.Hooks.Poststart
|
||||
|
||||
if len(poststart) != 3 {
|
||||
t.Error("Expected 3 Poststart hooks")
|
||||
}
|
||||
|
||||
poststop := conf.Hooks.Poststop
|
||||
|
||||
if len(poststop) != 4 {
|
||||
t.Error("Expected 4 Poststop hooks")
|
||||
}
|
||||
|
||||
}
|
||||
func TestSetupSeccomp(t *testing.T) {
|
||||
conf := &specs.LinuxSeccomp{
|
||||
DefaultAction: "SCMP_ACT_ERRNO",
|
||||
Architectures: []specs.Arch{specs.ArchX86_64, specs.ArchARM},
|
||||
Syscalls: []specs.LinuxSyscall{
|
||||
{
|
||||
Names: []string{"clone"},
|
||||
Action: "SCMP_ACT_ALLOW",
|
||||
Args: []specs.LinuxSeccompArg{
|
||||
{
|
||||
Index: 0,
|
||||
Value: 2080505856,
|
||||
ValueTwo: 0,
|
||||
Op: "SCMP_CMP_MASKED_EQ",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Names: []string{
|
||||
"select",
|
||||
"semctl",
|
||||
"semget",
|
||||
"semop",
|
||||
"semtimedop",
|
||||
"send",
|
||||
"sendfile",
|
||||
},
|
||||
Action: "SCMP_ACT_ALLOW",
|
||||
},
|
||||
},
|
||||
}
|
||||
seccomp, err := setupSeccomp(conf)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create Seccomp config: %v", err)
|
||||
}
|
||||
|
||||
if seccomp.DefaultAction != 2 { // SCMP_ACT_ERRNO
|
||||
t.Error("Wrong conversion for DefaultAction")
|
||||
}
|
||||
|
||||
if len(seccomp.Architectures) != 2 {
|
||||
t.Error("Wrong number of architectures")
|
||||
}
|
||||
|
||||
if seccomp.Architectures[0] != "amd64" || seccomp.Architectures[1] != "arm" {
|
||||
t.Error("Expected architectures are not found")
|
||||
}
|
||||
|
||||
calls := seccomp.Syscalls
|
||||
|
||||
callsLength := len(calls)
|
||||
if callsLength != 8 {
|
||||
t.Errorf("Expected 8 syscalls, got :%d", callsLength)
|
||||
}
|
||||
|
||||
for i, call := range calls {
|
||||
if i == 0 {
|
||||
expectedCloneSyscallArgs := configs.Arg{
|
||||
Index: 0,
|
||||
Op: 7, // SCMP_CMP_MASKED_EQ
|
||||
Value: 2080505856,
|
||||
ValueTwo: 0,
|
||||
}
|
||||
if expectedCloneSyscallArgs != *call.Args[0] {
|
||||
t.Errorf("Wrong arguments conversion for the clone syscall under test")
|
||||
}
|
||||
}
|
||||
if call.Action != 4 {
|
||||
t.Error("Wrong conversion for the clone syscall action")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestLinuxCgroupWithMemoryResource(t *testing.T) {
|
||||
cgroupsPath := "/user/cgroups/path/id"
|
||||
|
||||
spec := &specs.Spec{}
|
||||
devices := []specs.LinuxDeviceCgroup{
|
||||
{
|
||||
Allow: false,
|
||||
Access: "rwm",
|
||||
},
|
||||
}
|
||||
|
||||
limit := int64(100)
|
||||
reservation := int64(50)
|
||||
swap := int64(20)
|
||||
kernel := int64(40)
|
||||
kernelTCP := int64(45)
|
||||
swappiness := uint64(1)
|
||||
swappinessPtr := &swappiness
|
||||
disableOOMKiller := true
|
||||
resources := &specs.LinuxResources{
|
||||
Devices: devices,
|
||||
Memory: &specs.LinuxMemory{
|
||||
Limit: &limit,
|
||||
Reservation: &reservation,
|
||||
Swap: &swap,
|
||||
Kernel: &kernel,
|
||||
KernelTCP: &kernelTCP,
|
||||
Swappiness: swappinessPtr,
|
||||
DisableOOMKiller: &disableOOMKiller,
|
||||
},
|
||||
}
|
||||
spec.Linux = &specs.Linux{
|
||||
CgroupsPath: cgroupsPath,
|
||||
Resources: resources,
|
||||
}
|
||||
|
||||
opts := &CreateOpts{
|
||||
CgroupName: "ContainerID",
|
||||
UseSystemdCgroup: false,
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
cgroup, err := createCgroupConfig(opts)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create Cgroup config: %v", err)
|
||||
}
|
||||
|
||||
if cgroup.Path != cgroupsPath {
|
||||
t.Errorf("Wrong cgroupsPath, expected '%s' got '%s'", cgroupsPath, cgroup.Path)
|
||||
}
|
||||
if cgroup.Resources.Memory != limit {
|
||||
t.Errorf("Expected to have %d as memory limit, got %d", limit, cgroup.Resources.Memory)
|
||||
}
|
||||
if cgroup.Resources.MemoryReservation != reservation {
|
||||
t.Errorf("Expected to have %d as memory reservation, got %d", reservation, cgroup.Resources.MemoryReservation)
|
||||
}
|
||||
if cgroup.Resources.MemorySwap != swap {
|
||||
t.Errorf("Expected to have %d as swap, got %d", swap, cgroup.Resources.MemorySwap)
|
||||
}
|
||||
if cgroup.Resources.KernelMemory != kernel {
|
||||
t.Errorf("Expected to have %d as Kernel Memory, got %d", kernel, cgroup.Resources.KernelMemory)
|
||||
}
|
||||
if cgroup.Resources.KernelMemoryTCP != kernelTCP {
|
||||
t.Errorf("Expected to have %d as TCP Kernel Memory, got %d", kernelTCP, cgroup.Resources.KernelMemoryTCP)
|
||||
}
|
||||
if cgroup.Resources.MemorySwappiness != swappinessPtr {
|
||||
t.Errorf("Expected to have %d as memory swappiness, got %d", swappinessPtr, cgroup.Resources.MemorySwappiness)
|
||||
}
|
||||
if cgroup.Resources.OomKillDisable != disableOOMKiller {
|
||||
t.Errorf("The OOMKiller should be enabled")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinuxCgroupSystemd(t *testing.T) {
|
||||
cgroupsPath := "parent:scopeprefix:name"
|
||||
|
||||
spec := &specs.Spec{}
|
||||
spec.Linux = &specs.Linux{
|
||||
CgroupsPath: cgroupsPath,
|
||||
}
|
||||
|
||||
opts := &CreateOpts{
|
||||
UseSystemdCgroup: true,
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
cgroup, err := createCgroupConfig(opts)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create Cgroup config: %v", err)
|
||||
}
|
||||
|
||||
expectedParent := "parent"
|
||||
if cgroup.Parent != expectedParent {
|
||||
t.Errorf("Expected to have %s as Parent instead of %s", expectedParent, cgroup.Parent)
|
||||
}
|
||||
|
||||
expectedScopePrefix := "scopeprefix"
|
||||
if cgroup.ScopePrefix != expectedScopePrefix {
|
||||
t.Errorf("Expected to have %s as ScopePrefix instead of %s", expectedScopePrefix, cgroup.ScopePrefix)
|
||||
}
|
||||
|
||||
expectedName := "name"
|
||||
if cgroup.Name != expectedName {
|
||||
t.Errorf("Expected to have %s as Name instead of %s", expectedName, cgroup.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinuxCgroupSystemdWithEmptyPath(t *testing.T) {
|
||||
cgroupsPath := ""
|
||||
|
||||
spec := &specs.Spec{}
|
||||
spec.Linux = &specs.Linux{
|
||||
CgroupsPath: cgroupsPath,
|
||||
}
|
||||
|
||||
opts := &CreateOpts{
|
||||
CgroupName: "ContainerID",
|
||||
UseSystemdCgroup: true,
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
cgroup, err := createCgroupConfig(opts)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create Cgroup config: %v", err)
|
||||
}
|
||||
|
||||
expectedParent := "system.slice"
|
||||
if cgroup.Parent != expectedParent {
|
||||
t.Errorf("Expected to have %s as Parent instead of %s", expectedParent, cgroup.Parent)
|
||||
}
|
||||
|
||||
expectedScopePrefix := "runc"
|
||||
if cgroup.ScopePrefix != expectedScopePrefix {
|
||||
t.Errorf("Expected to have %s as ScopePrefix instead of %s", expectedScopePrefix, cgroup.ScopePrefix)
|
||||
}
|
||||
|
||||
if cgroup.Name != opts.CgroupName {
|
||||
t.Errorf("Expected to have %s as Name instead of %s", opts.CgroupName, cgroup.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinuxCgroupSystemdWithInvalidPath(t *testing.T) {
|
||||
cgroupsPath := "/user/cgroups/path/id"
|
||||
|
||||
spec := &specs.Spec{}
|
||||
spec.Linux = &specs.Linux{
|
||||
CgroupsPath: cgroupsPath,
|
||||
}
|
||||
|
||||
opts := &CreateOpts{
|
||||
CgroupName: "ContainerID",
|
||||
UseSystemdCgroup: true,
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
_, err := createCgroupConfig(opts)
|
||||
if err == nil {
|
||||
t.Error("Expected to produce an error if not using the correct format for cgroup paths belonging to systemd")
|
||||
}
|
||||
}
|
||||
func TestLinuxCgroupsPathSpecified(t *testing.T) {
|
||||
cgroupsPath := "/user/cgroups/path/id"
|
||||
|
||||
spec := &specs.Spec{}
|
||||
spec.Linux = &specs.Linux{
|
||||
CgroupsPath: cgroupsPath,
|
||||
}
|
||||
|
||||
opts := &CreateOpts{
|
||||
CgroupName: "ContainerID",
|
||||
UseSystemdCgroup: false,
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
cgroup, err := createCgroupConfig(opts)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create Cgroup config: %v", err)
|
||||
}
|
||||
|
||||
if cgroup.Path != cgroupsPath {
|
||||
t.Errorf("Wrong cgroupsPath, expected '%s' got '%s'", cgroupsPath, cgroup.Path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLinuxCgroupsPathNotSpecified(t *testing.T) {
|
||||
spec := &specs.Spec{}
|
||||
opts := &CreateOpts{
|
||||
CgroupName: "ContainerID",
|
||||
UseSystemdCgroup: false,
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
cgroup, err := createCgroupConfig(opts)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create Cgroup config: %v", err)
|
||||
}
|
||||
|
||||
if cgroup.Path != "" {
|
||||
t.Errorf("Wrong cgroupsPath, expected it to be empty string, got '%s'", cgroup.Path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpecconvExampleValidate(t *testing.T) {
|
||||
spec := Example()
|
||||
spec.Root.Path = "/"
|
||||
|
||||
opts := &CreateOpts{
|
||||
CgroupName: "ContainerID",
|
||||
UseSystemdCgroup: false,
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
config, err := CreateLibcontainerConfig(opts)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create libcontainer config: %v", err)
|
||||
}
|
||||
|
||||
validator := validate.New()
|
||||
if err := validator.Validate(config); err != nil {
|
||||
t.Errorf("Expected specconv to produce valid container config: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDupNamespaces(t *testing.T) {
|
||||
spec := &specs.Spec{
|
||||
Linux: &specs.Linux{
|
||||
Namespaces: []specs.LinuxNamespace{
|
||||
{
|
||||
Type: "pid",
|
||||
},
|
||||
{
|
||||
Type: "pid",
|
||||
Path: "/proc/1/ns/pid",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err := CreateLibcontainerConfig(&CreateOpts{
|
||||
Spec: spec,
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Duplicated namespaces should be forbidden")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRootlessSpecconvValidate(t *testing.T) {
|
||||
if _, err := os.Stat("/proc/self/ns/user"); os.IsNotExist(err) {
|
||||
t.Skip("userns is unsupported")
|
||||
}
|
||||
|
||||
spec := Example()
|
||||
spec.Root.Path = "/"
|
||||
ToRootless(spec)
|
||||
|
||||
opts := &CreateOpts{
|
||||
CgroupName: "ContainerID",
|
||||
UseSystemdCgroup: false,
|
||||
Spec: spec,
|
||||
Rootless: true,
|
||||
}
|
||||
|
||||
config, err := CreateLibcontainerConfig(opts)
|
||||
if err != nil {
|
||||
t.Errorf("Couldn't create libcontainer config: %v", err)
|
||||
}
|
||||
|
||||
validator := validate.New()
|
||||
if err := validator.Validate(config); err != nil {
|
||||
t.Errorf("Expected specconv to produce valid rootless container config: %v", err)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue