Files
runc/libcontainer/specconv/spec_linux_test.go
Kenta Tada b54fd85bbf libcontainer: change seccomp test for clone syscall
This commit changes the value of seccomp test for clone syscall.
Also hardcoded values should be changed because it is unclear to
understand what flags are tested.

Related issues:

* https://github.com/containerd/containerd/pull/3314
* https://github.com/moby/moby/pull/39308
* https://github.com/opencontainers/runtime-tools/pull/694

Signed-off-by: Kenta Tada <Kenta.Tada@sony.com>
2019-06-04 18:52:00 +09:00

453 lines
10 KiB
Go

// +build linux
package specconv
import (
"os"
"strings"
"testing"
"golang.org/x/sys/unix"
"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: unix.CLONE_NEWNS | unix.CLONE_NEWUTS | unix.CLONE_NEWIPC | unix.CLONE_NEWUSER | unix.CLONE_NEWPID | unix.CLONE_NEWNET | unix.CLONE_NEWCGROUP,
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: unix.CLONE_NEWNS | unix.CLONE_NEWUTS | unix.CLONE_NEWIPC | unix.CLONE_NEWUSER | unix.CLONE_NEWPID | unix.CLONE_NEWNET | unix.CLONE_NEWCGROUP,
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{
Root: &specs.Root{
Path: "rootfs",
},
Linux: &specs.Linux{
Namespaces: []specs.LinuxNamespace{
{
Type: "pid",
},
{
Type: "pid",
Path: "/proc/1/ns/pid",
},
},
},
}
_, err := CreateLibcontainerConfig(&CreateOpts{
Spec: spec,
})
if !strings.Contains(err.Error(), "malformed spec file: duplicated ns") {
t.Errorf("Duplicated namespaces should be forbidden")
}
}
func TestNonZeroEUIDCompatibleSpecconvValidate(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,
RootlessEUID: true,
RootlessCgroups: 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)
}
}