summaryrefslogtreecommitdiffhomepage
path: root/runsc/specutils
diff options
context:
space:
mode:
Diffstat (limited to 'runsc/specutils')
-rw-r--r--runsc/specutils/BUILD34
-rw-r--r--runsc/specutils/seccomp/BUILD34
-rw-r--r--runsc/specutils/seccomp/seccomp_amd64_state_autogen.go5
-rw-r--r--runsc/specutils/seccomp/seccomp_arm64_state_autogen.go5
-rw-r--r--runsc/specutils/seccomp/seccomp_state_autogen.go3
-rw-r--r--runsc/specutils/seccomp/seccomp_test.go414
-rw-r--r--runsc/specutils/specutils_state_autogen.go3
-rw-r--r--runsc/specutils/specutils_test.go265
8 files changed, 16 insertions, 747 deletions
diff --git a/runsc/specutils/BUILD b/runsc/specutils/BUILD
deleted file mode 100644
index 679d8bc8e..000000000
--- a/runsc/specutils/BUILD
+++ /dev/null
@@ -1,34 +0,0 @@
-load("//tools:defs.bzl", "go_library", "go_test")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "specutils",
- srcs = [
- "cri.go",
- "fs.go",
- "namespace.go",
- "specutils.go",
- ],
- visibility = ["//:sandbox"],
- deps = [
- "//pkg/abi/linux",
- "//pkg/bits",
- "//pkg/log",
- "//pkg/sentry/kernel/auth",
- "//runsc/config",
- "@com_github_cenkalti_backoff//:go_default_library",
- "@com_github_mohae_deepcopy//:go_default_library",
- "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
- "@com_github_syndtr_gocapability//capability:go_default_library",
- "@org_golang_x_sys//unix:go_default_library",
- ],
-)
-
-go_test(
- name = "specutils_test",
- size = "small",
- srcs = ["specutils_test.go"],
- library = ":specutils",
- deps = ["@com_github_opencontainers_runtime_spec//specs-go:go_default_library"],
-)
diff --git a/runsc/specutils/seccomp/BUILD b/runsc/specutils/seccomp/BUILD
deleted file mode 100644
index 3520f2d6d..000000000
--- a/runsc/specutils/seccomp/BUILD
+++ /dev/null
@@ -1,34 +0,0 @@
-load("//tools:defs.bzl", "go_library", "go_test")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "seccomp",
- srcs = [
- "audit_amd64.go",
- "audit_arm64.go",
- "seccomp.go",
- ],
- visibility = ["//:sandbox"],
- deps = [
- "//pkg/abi/linux",
- "//pkg/bpf",
- "//pkg/log",
- "//pkg/seccomp",
- "//pkg/sentry/kernel",
- "//pkg/sentry/syscalls/linux",
- "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
- ],
-)
-
-go_test(
- name = "seccomp_test",
- size = "small",
- srcs = ["seccomp_test.go"],
- library = ":seccomp",
- deps = [
- "//pkg/binary",
- "//pkg/bpf",
- "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
- ],
-)
diff --git a/runsc/specutils/seccomp/seccomp_amd64_state_autogen.go b/runsc/specutils/seccomp/seccomp_amd64_state_autogen.go
new file mode 100644
index 000000000..27a96018b
--- /dev/null
+++ b/runsc/specutils/seccomp/seccomp_amd64_state_autogen.go
@@ -0,0 +1,5 @@
+// automatically generated by stateify.
+
+// +build amd64
+
+package seccomp
diff --git a/runsc/specutils/seccomp/seccomp_arm64_state_autogen.go b/runsc/specutils/seccomp/seccomp_arm64_state_autogen.go
new file mode 100644
index 000000000..96c64c23d
--- /dev/null
+++ b/runsc/specutils/seccomp/seccomp_arm64_state_autogen.go
@@ -0,0 +1,5 @@
+// automatically generated by stateify.
+
+// +build arm64
+
+package seccomp
diff --git a/runsc/specutils/seccomp/seccomp_state_autogen.go b/runsc/specutils/seccomp/seccomp_state_autogen.go
new file mode 100644
index 000000000..e16b5d7c2
--- /dev/null
+++ b/runsc/specutils/seccomp/seccomp_state_autogen.go
@@ -0,0 +1,3 @@
+// automatically generated by stateify.
+
+package seccomp
diff --git a/runsc/specutils/seccomp/seccomp_test.go b/runsc/specutils/seccomp/seccomp_test.go
deleted file mode 100644
index 850c237ba..000000000
--- a/runsc/specutils/seccomp/seccomp_test.go
+++ /dev/null
@@ -1,414 +0,0 @@
-// Copyright 2020 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package seccomp
-
-import (
- "fmt"
- "syscall"
- "testing"
-
- specs "github.com/opencontainers/runtime-spec/specs-go"
- "gvisor.dev/gvisor/pkg/binary"
- "gvisor.dev/gvisor/pkg/bpf"
-)
-
-type seccompData struct {
- nr uint32
- arch uint32
- instructionPointer uint64
- args [6]uint64
-}
-
-// asInput converts a seccompData to a bpf.Input.
-func asInput(d seccompData) bpf.Input {
- return bpf.InputBytes{binary.Marshal(nil, binary.LittleEndian, d), binary.LittleEndian}
-}
-
-// testInput creates an Input struct with given seccomp input values.
-func testInput(arch uint32, syscallName string, args *[6]uint64) bpf.Input {
- syscallNo, err := lookupSyscallNo(arch, syscallName)
- if err != nil {
- // Assume tests set valid syscall names.
- panic(err)
- }
-
- if args == nil {
- argArray := [6]uint64{0, 0, 0, 0, 0, 0}
- args = &argArray
- }
-
- data := seccompData{
- nr: syscallNo,
- arch: arch,
- args: *args,
- }
-
- return asInput(data)
-}
-
-// testCase holds a seccomp test case.
-type testCase struct {
- name string
- config specs.LinuxSeccomp
- input bpf.Input
- expected uint32
-}
-
-var (
- // seccompTests is a list of speccomp test cases.
- seccompTests = []testCase{
- {
- name: "default_allow",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActAllow,
- },
- input: testInput(nativeArchAuditNo, "read", nil),
- expected: uint32(allowAction),
- },
- {
- name: "default_deny",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActErrno,
- },
- input: testInput(nativeArchAuditNo, "read", nil),
- expected: uint32(errnoAction),
- },
- {
- name: "deny_arch",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActAllow,
- Syscalls: []specs.LinuxSyscall{
- {
- Names: []string{
- "getcwd",
- },
- Action: specs.ActErrno,
- },
- },
- },
- // Syscall matches but the arch is AUDIT_ARCH_X86 so the return
- // value is the bad arch action.
- input: asInput(seccompData{nr: 183, arch: 0x40000003}), //
- expected: uint32(killThreadAction),
- },
- {
- name: "match_name_errno",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActAllow,
- Syscalls: []specs.LinuxSyscall{
- {
- Names: []string{
- "getcwd",
- "chmod",
- },
- Action: specs.ActErrno,
- },
- {
- Names: []string{
- "write",
- },
- Action: specs.ActTrace,
- },
- },
- },
- input: testInput(nativeArchAuditNo, "getcwd", nil),
- expected: uint32(errnoAction),
- },
- {
- name: "match_name_trace",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActAllow,
- Syscalls: []specs.LinuxSyscall{
- {
- Names: []string{
- "getcwd",
- "chmod",
- },
- Action: specs.ActErrno,
- },
- {
- Names: []string{
- "write",
- },
- Action: specs.ActTrace,
- },
- },
- },
- input: testInput(nativeArchAuditNo, "write", nil),
- expected: uint32(traceAction),
- },
- {
- name: "no_match_name_allow",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActAllow,
- Syscalls: []specs.LinuxSyscall{
- {
- Names: []string{
- "getcwd",
- "chmod",
- },
- Action: specs.ActErrno,
- },
- {
- Names: []string{
- "write",
- },
- Action: specs.ActTrace,
- },
- },
- },
- input: testInput(nativeArchAuditNo, "openat", nil),
- expected: uint32(allowAction),
- },
- {
- name: "simple_match_args",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActAllow,
- Syscalls: []specs.LinuxSyscall{
- {
- Names: []string{
- "clone",
- },
- Args: []specs.LinuxSeccompArg{
- {
- Index: 0,
- Value: syscall.CLONE_FS,
- Op: specs.OpEqualTo,
- },
- },
- Action: specs.ActErrno,
- },
- },
- },
- input: testInput(nativeArchAuditNo, "clone", &[6]uint64{syscall.CLONE_FS}),
- expected: uint32(errnoAction),
- },
- {
- name: "match_args_or",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActAllow,
- Syscalls: []specs.LinuxSyscall{
- {
- Names: []string{
- "clone",
- },
- Args: []specs.LinuxSeccompArg{
- {
- Index: 0,
- Value: syscall.CLONE_FS,
- Op: specs.OpEqualTo,
- },
- {
- Index: 0,
- Value: syscall.CLONE_VM,
- Op: specs.OpEqualTo,
- },
- },
- Action: specs.ActErrno,
- },
- },
- },
- input: testInput(nativeArchAuditNo, "clone", &[6]uint64{syscall.CLONE_FS}),
- expected: uint32(errnoAction),
- },
- {
- name: "match_args_and",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActAllow,
- Syscalls: []specs.LinuxSyscall{
- {
- Names: []string{
- "getsockopt",
- },
- Args: []specs.LinuxSeccompArg{
- {
- Index: 1,
- Value: syscall.SOL_SOCKET,
- Op: specs.OpEqualTo,
- },
- {
- Index: 2,
- Value: syscall.SO_PEERCRED,
- Op: specs.OpEqualTo,
- },
- },
- Action: specs.ActErrno,
- },
- },
- },
- input: testInput(nativeArchAuditNo, "getsockopt", &[6]uint64{0, syscall.SOL_SOCKET, syscall.SO_PEERCRED}),
- expected: uint32(errnoAction),
- },
- {
- name: "no_match_args_and",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActAllow,
- Syscalls: []specs.LinuxSyscall{
- {
- Names: []string{
- "getsockopt",
- },
- Args: []specs.LinuxSeccompArg{
- {
- Index: 1,
- Value: syscall.SOL_SOCKET,
- Op: specs.OpEqualTo,
- },
- {
- Index: 2,
- Value: syscall.SO_PEERCRED,
- Op: specs.OpEqualTo,
- },
- },
- Action: specs.ActErrno,
- },
- },
- },
- input: testInput(nativeArchAuditNo, "getsockopt", &[6]uint64{0, syscall.SOL_SOCKET}),
- expected: uint32(allowAction),
- },
- {
- name: "Simple args (no match)",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActAllow,
- Syscalls: []specs.LinuxSyscall{
- {
- Names: []string{
- "clone",
- },
- Args: []specs.LinuxSeccompArg{
- {
- Index: 0,
- Value: syscall.CLONE_FS,
- Op: specs.OpEqualTo,
- },
- },
- Action: specs.ActErrno,
- },
- },
- },
- input: testInput(nativeArchAuditNo, "clone", &[6]uint64{syscall.CLONE_VM}),
- expected: uint32(allowAction),
- },
- {
- name: "OpMaskedEqual (match)",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActAllow,
- Syscalls: []specs.LinuxSyscall{
- {
- Names: []string{
- "clone",
- },
- Args: []specs.LinuxSeccompArg{
- {
- Index: 0,
- Value: syscall.CLONE_FS,
- ValueTwo: syscall.CLONE_FS,
- Op: specs.OpMaskedEqual,
- },
- },
- Action: specs.ActErrno,
- },
- },
- },
- input: testInput(nativeArchAuditNo, "clone", &[6]uint64{syscall.CLONE_FS | syscall.CLONE_VM}),
- expected: uint32(errnoAction),
- },
- {
- name: "OpMaskedEqual (no match)",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActAllow,
- Syscalls: []specs.LinuxSyscall{
- {
- Names: []string{
- "clone",
- },
- Args: []specs.LinuxSeccompArg{
- {
- Index: 0,
- Value: syscall.CLONE_FS | syscall.CLONE_VM,
- ValueTwo: syscall.CLONE_FS | syscall.CLONE_VM,
- Op: specs.OpMaskedEqual,
- },
- },
- Action: specs.ActErrno,
- },
- },
- },
- input: testInput(nativeArchAuditNo, "clone", &[6]uint64{syscall.CLONE_FS}),
- expected: uint32(allowAction),
- },
- {
- name: "OpMaskedEqual (clone)",
- config: specs.LinuxSeccomp{
- DefaultAction: specs.ActErrno,
- Syscalls: []specs.LinuxSyscall{
- {
- Names: []string{
- "clone",
- },
- // This comes from the Docker default seccomp
- // profile for clone.
- Args: []specs.LinuxSeccompArg{
- {
- Index: 0,
- Value: 0x7e020000,
- ValueTwo: 0x0,
- Op: specs.OpMaskedEqual,
- },
- },
- Action: specs.ActAllow,
- },
- },
- },
- input: testInput(nativeArchAuditNo, "clone", &[6]uint64{0x50f00}),
- expected: uint32(allowAction),
- },
- }
-)
-
-// TestRunscSeccomp generates seccomp programs from OCI config and executes
-// them using runsc's library, comparing against expected results.
-func TestRunscSeccomp(t *testing.T) {
- for _, tc := range seccompTests {
- t.Run(tc.name, func(t *testing.T) {
- runscProgram, err := BuildProgram(&tc.config)
- if err != nil {
- t.Fatalf("generating runsc BPF: %v", err)
- }
-
- if err := checkProgram(runscProgram, tc.input, tc.expected); err != nil {
- t.Fatalf("running runsc BPF: %v", err)
- }
- })
- }
-}
-
-// checkProgram runs the given program over the given input and checks the
-// result against the expected output.
-func checkProgram(p bpf.Program, in bpf.Input, expected uint32) error {
- result, err := bpf.Exec(p, in)
- if err != nil {
- return err
- }
-
- if result != expected {
- // Include a decoded version of the program in output for debugging purposes.
- decoded, _ := bpf.DecodeProgram(p)
- return fmt.Errorf("Unexpected result: got: %d, expected: %d\nBPF Program\n%s", result, expected, decoded)
- }
-
- return nil
-}
diff --git a/runsc/specutils/specutils_state_autogen.go b/runsc/specutils/specutils_state_autogen.go
new file mode 100644
index 000000000..11eefbaa2
--- /dev/null
+++ b/runsc/specutils/specutils_state_autogen.go
@@ -0,0 +1,3 @@
+// automatically generated by stateify.
+
+package specutils
diff --git a/runsc/specutils/specutils_test.go b/runsc/specutils/specutils_test.go
deleted file mode 100644
index 2c86fffe8..000000000
--- a/runsc/specutils/specutils_test.go
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package specutils
-
-import (
- "fmt"
- "os/exec"
- "strings"
- "testing"
- "time"
-
- specs "github.com/opencontainers/runtime-spec/specs-go"
-)
-
-func TestWaitForReadyHappy(t *testing.T) {
- cmd := exec.Command("/bin/sleep", "1000")
- if err := cmd.Start(); err != nil {
- t.Fatalf("cmd.Start() failed, err: %v", err)
- }
- defer cmd.Wait()
-
- var count int
- err := WaitForReady(cmd.Process.Pid, 5*time.Second, func() (bool, error) {
- if count < 3 {
- count++
- return false, nil
- }
- return true, nil
- })
- if err != nil {
- t.Errorf("ProcessWaitReady got: %v, expected: nil", err)
- }
- cmd.Process.Kill()
-}
-
-func TestWaitForReadyFail(t *testing.T) {
- cmd := exec.Command("/bin/sleep", "1000")
- if err := cmd.Start(); err != nil {
- t.Fatalf("cmd.Start() failed, err: %v", err)
- }
- defer cmd.Wait()
-
- var count int
- err := WaitForReady(cmd.Process.Pid, 5*time.Second, func() (bool, error) {
- if count < 3 {
- count++
- return false, nil
- }
- return false, fmt.Errorf("Fake error")
- })
- if err == nil {
- t.Errorf("ProcessWaitReady got: nil, expected: error")
- }
- cmd.Process.Kill()
-}
-
-func TestWaitForReadyNotRunning(t *testing.T) {
- cmd := exec.Command("/bin/true")
- if err := cmd.Start(); err != nil {
- t.Fatalf("cmd.Start() failed, err: %v", err)
- }
- defer cmd.Wait()
-
- err := WaitForReady(cmd.Process.Pid, 5*time.Second, func() (bool, error) {
- return false, nil
- })
- if err != nil && !strings.Contains(err.Error(), "terminated") {
- t.Errorf("ProcessWaitReady got: %v, expected: process terminated", err)
- }
- if err == nil {
- t.Errorf("ProcessWaitReady incorrectly succeeded")
- }
-}
-
-func TestWaitForReadyTimeout(t *testing.T) {
- cmd := exec.Command("/bin/sleep", "1000")
- if err := cmd.Start(); err != nil {
- t.Fatalf("cmd.Start() failed, err: %v", err)
- }
- defer cmd.Wait()
-
- err := WaitForReady(cmd.Process.Pid, 50*time.Millisecond, func() (bool, error) {
- return false, nil
- })
- if !strings.Contains(err.Error(), "not running yet") {
- t.Errorf("ProcessWaitReady got: %v, expected: not running yet", err)
- }
- cmd.Process.Kill()
-}
-
-func TestSpecInvalid(t *testing.T) {
- for _, test := range []struct {
- name string
- spec specs.Spec
- error string
- }{
- {
- name: "valid",
- spec: specs.Spec{
- Root: &specs.Root{Path: "/"},
- Process: &specs.Process{
- Args: []string{"/bin/true"},
- },
- Mounts: []specs.Mount{
- {
- Source: "src",
- Destination: "/dst",
- },
- },
- },
- error: "",
- },
- {
- name: "valid+warning",
- spec: specs.Spec{
- Root: &specs.Root{Path: "/"},
- Process: &specs.Process{
- Args: []string{"/bin/true"},
- // This is normally set by docker and will just cause warnings to be logged.
- ApparmorProfile: "someprofile",
- },
- // This is normally set by docker and will just cause warnings to be logged.
- Linux: &specs.Linux{Seccomp: &specs.LinuxSeccomp{}},
- },
- error: "",
- },
- {
- name: "no root",
- spec: specs.Spec{
- Process: &specs.Process{
- Args: []string{"/bin/true"},
- },
- },
- error: "must be defined",
- },
- {
- name: "empty root",
- spec: specs.Spec{
- Root: &specs.Root{},
- Process: &specs.Process{
- Args: []string{"/bin/true"},
- },
- },
- error: "must be defined",
- },
- {
- name: "no process",
- spec: specs.Spec{
- Root: &specs.Root{Path: "/"},
- },
- error: "must be defined",
- },
- {
- name: "empty args",
- spec: specs.Spec{
- Root: &specs.Root{Path: "/"},
- Process: &specs.Process{},
- },
- error: "must be defined",
- },
- {
- name: "selinux",
- spec: specs.Spec{
- Root: &specs.Root{Path: "/"},
- Process: &specs.Process{
- Args: []string{"/bin/true"},
- SelinuxLabel: "somelabel",
- },
- },
- error: "is not supported",
- },
- {
- name: "solaris",
- spec: specs.Spec{
- Root: &specs.Root{Path: "/"},
- Process: &specs.Process{
- Args: []string{"/bin/true"},
- },
- Solaris: &specs.Solaris{},
- },
- error: "is not supported",
- },
- {
- name: "windows",
- spec: specs.Spec{
- Root: &specs.Root{Path: "/"},
- Process: &specs.Process{
- Args: []string{"/bin/true"},
- },
- Windows: &specs.Windows{},
- },
- error: "is not supported",
- },
- {
- name: "relative mount destination",
- spec: specs.Spec{
- Root: &specs.Root{Path: "/"},
- Process: &specs.Process{
- Args: []string{"/bin/true"},
- },
- Mounts: []specs.Mount{
- {
- Source: "src",
- Destination: "dst",
- },
- },
- },
- error: "must be an absolute path",
- },
- {
- name: "invalid mount option",
- spec: specs.Spec{
- Root: &specs.Root{Path: "/"},
- Process: &specs.Process{
- Args: []string{"/bin/true"},
- },
- Mounts: []specs.Mount{
- {
- Source: "/src",
- Destination: "/dst",
- Type: "bind",
- Options: []string{"shared"},
- },
- },
- },
- error: "is not supported",
- },
- {
- name: "invalid rootfs propagation",
- spec: specs.Spec{
- Root: &specs.Root{Path: "/"},
- Process: &specs.Process{
- Args: []string{"/bin/true"},
- },
- Linux: &specs.Linux{
- RootfsPropagation: "foo",
- },
- },
- error: "root mount propagation option must specify private or slave",
- },
- } {
- err := ValidateSpec(&test.spec)
- if len(test.error) == 0 {
- if err != nil {
- t.Errorf("ValidateSpec(%q) failed, err: %v", test.name, err)
- }
- } else {
- if err == nil || !strings.Contains(err.Error(), test.error) {
- t.Errorf("ValidateSpec(%q) wrong error, got: %v, want: .*%s.*", test.name, err, test.error)
- }
- }
- }
-}