summaryrefslogtreecommitdiffhomepage
path: root/pkg/seccomp
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/seccomp')
-rw-r--r--pkg/seccomp/BUILD55
-rw-r--r--pkg/seccomp/seccomp_amd64_state_autogen.go5
-rw-r--r--pkg/seccomp/seccomp_arm64_state_autogen.go5
-rw-r--r--pkg/seccomp/seccomp_state_autogen.go3
-rw-r--r--pkg/seccomp/seccomp_test.go1059
-rw-r--r--pkg/seccomp/seccomp_test_victim.go116
-rw-r--r--pkg/seccomp/seccomp_test_victim_amd64.go32
-rw-r--r--pkg/seccomp/seccomp_test_victim_arm64.go29
-rw-r--r--pkg/seccomp/seccomp_unsafe_state_autogen.go3
9 files changed, 16 insertions, 1291 deletions
diff --git a/pkg/seccomp/BUILD b/pkg/seccomp/BUILD
deleted file mode 100644
index e828894b0..000000000
--- a/pkg/seccomp/BUILD
+++ /dev/null
@@ -1,55 +0,0 @@
-load("//tools:defs.bzl", "go_binary", "go_embed_data", "go_library", "go_test")
-
-package(licenses = ["notice"])
-
-go_binary(
- name = "victim",
- testonly = 1,
- srcs = [
- "seccomp_test_victim.go",
- "seccomp_test_victim_amd64.go",
- "seccomp_test_victim_arm64.go",
- ],
- nogo = False,
- deps = [":seccomp"],
-)
-
-go_embed_data(
- name = "victim_data",
- testonly = 1,
- src = "victim",
- package = "seccomp",
- var = "victimData",
-)
-
-go_library(
- name = "seccomp",
- srcs = [
- "seccomp.go",
- "seccomp_amd64.go",
- "seccomp_arm64.go",
- "seccomp_rules.go",
- "seccomp_unsafe.go",
- ],
- visibility = ["//:sandbox"],
- deps = [
- "//pkg/abi/linux",
- "//pkg/bpf",
- "//pkg/log",
- ],
-)
-
-go_test(
- name = "seccomp_test",
- size = "small",
- srcs = [
- "seccomp_test.go",
- ":victim_data",
- ],
- library = ":seccomp",
- deps = [
- "//pkg/abi/linux",
- "//pkg/bpf",
- "//pkg/usermem",
- ],
-)
diff --git a/pkg/seccomp/seccomp_amd64_state_autogen.go b/pkg/seccomp/seccomp_amd64_state_autogen.go
new file mode 100644
index 000000000..27a96018b
--- /dev/null
+++ b/pkg/seccomp/seccomp_amd64_state_autogen.go
@@ -0,0 +1,5 @@
+// automatically generated by stateify.
+
+// +build amd64
+
+package seccomp
diff --git a/pkg/seccomp/seccomp_arm64_state_autogen.go b/pkg/seccomp/seccomp_arm64_state_autogen.go
new file mode 100644
index 000000000..96c64c23d
--- /dev/null
+++ b/pkg/seccomp/seccomp_arm64_state_autogen.go
@@ -0,0 +1,5 @@
+// automatically generated by stateify.
+
+// +build arm64
+
+package seccomp
diff --git a/pkg/seccomp/seccomp_state_autogen.go b/pkg/seccomp/seccomp_state_autogen.go
new file mode 100644
index 000000000..e16b5d7c2
--- /dev/null
+++ b/pkg/seccomp/seccomp_state_autogen.go
@@ -0,0 +1,3 @@
+// automatically generated by stateify.
+
+package seccomp
diff --git a/pkg/seccomp/seccomp_test.go b/pkg/seccomp/seccomp_test.go
deleted file mode 100644
index db06d1f1b..000000000
--- a/pkg/seccomp/seccomp_test.go
+++ /dev/null
@@ -1,1059 +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 seccomp
-
-import (
- "bytes"
- "fmt"
- "io"
- "io/ioutil"
- "math"
- "math/rand"
- "os"
- "os/exec"
- "strings"
- "testing"
- "time"
-
- "gvisor.dev/gvisor/pkg/abi/linux"
- "gvisor.dev/gvisor/pkg/bpf"
- "gvisor.dev/gvisor/pkg/usermem"
-)
-
-// newVictim makes a victim binary.
-func newVictim() (string, error) {
- f, err := ioutil.TempFile("", "victim")
- if err != nil {
- return "", err
- }
- defer f.Close()
- path := f.Name()
- if _, err := io.Copy(f, bytes.NewBuffer(victimData)); err != nil {
- os.Remove(path)
- return "", err
- }
- if err := os.Chmod(path, 0755); err != nil {
- os.Remove(path)
- return "", err
- }
- return path, nil
-}
-
-// dataAsInput converts a linux.SeccompData to a bpf.Input.
-func dataAsInput(d *linux.SeccompData) bpf.Input {
- buf := make([]byte, d.SizeBytes())
- d.MarshalUnsafe(buf)
- return bpf.InputBytes{
- Data: buf,
- Order: usermem.ByteOrder,
- }
-}
-
-func TestBasic(t *testing.T) {
- type spec struct {
- // desc is the test's description.
- desc string
-
- // data is the input data.
- data linux.SeccompData
-
- // want is the expected return value of the BPF program.
- want linux.BPFAction
- }
-
- for _, test := range []struct {
- name string
- ruleSets []RuleSet
- defaultAction linux.BPFAction
- badArchAction linux.BPFAction
- specs []spec
- }{
- {
- name: "Single syscall",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{1: {}},
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "syscall allowed",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "syscall disallowed",
- data: linux.SeccompData{Nr: 2, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- {
- name: "Multiple rulesets",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- EqualTo(0x1),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- {
- Rules: SyscallRules{
- 1: {},
- 2: {},
- },
- Action: linux.SECCOMP_RET_TRAP,
- },
- },
- defaultAction: linux.SECCOMP_RET_KILL_THREAD,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "allowed (1a)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x1}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "allowed (1b)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "syscall 1 matched 2nd rule",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "no match",
- data: linux.SeccompData{Nr: 0, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_KILL_THREAD,
- },
- },
- },
- {
- name: "Multiple syscalls",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: {},
- 3: {},
- 5: {},
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "allowed (1)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "allowed (3)",
- data: linux.SeccompData{Nr: 3, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "allowed (5)",
- data: linux.SeccompData{Nr: 5, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "disallowed (0)",
- data: linux.SeccompData{Nr: 0, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "disallowed (2)",
- data: linux.SeccompData{Nr: 2, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "disallowed (4)",
- data: linux.SeccompData{Nr: 4, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "disallowed (6)",
- data: linux.SeccompData{Nr: 6, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "disallowed (100)",
- data: linux.SeccompData{Nr: 100, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- {
- name: "Wrong architecture",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: {},
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "arch (123)",
- data: linux.SeccompData{Nr: 1, Arch: 123},
- want: linux.SECCOMP_RET_KILL_THREAD,
- },
- },
- },
- {
- name: "Syscall disallowed",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: {},
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "action trap",
- data: linux.SeccompData{Nr: 2, Arch: LINUX_AUDIT_ARCH},
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- {
- name: "Syscall arguments",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- MatchAny{},
- EqualTo(0xf),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "allowed",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0xf, 0xf}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "disallowed",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0xf, 0xe}},
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- {
- name: "Multiple arguments",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- EqualTo(0xf),
- },
- {
- EqualTo(0xe),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "match first rule",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0xf}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "match 2nd rule",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0xe}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- },
- },
- {
- name: "EqualTo",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- EqualTo(0),
- EqualTo(math.MaxUint64 - 1),
- EqualTo(math.MaxUint32),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "argument allowed (all match)",
- data: linux.SeccompData{
- Nr: 1,
- Arch: LINUX_AUDIT_ARCH,
- Args: [6]uint64{0, math.MaxUint64 - 1, math.MaxUint32},
- },
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "argument disallowed (one mismatch)",
- data: linux.SeccompData{
- Nr: 1,
- Arch: LINUX_AUDIT_ARCH,
- Args: [6]uint64{0, math.MaxUint64, math.MaxUint32},
- },
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "argument disallowed (multiple mismatch)",
- data: linux.SeccompData{
- Nr: 1,
- Arch: LINUX_AUDIT_ARCH,
- Args: [6]uint64{0, math.MaxUint64, math.MaxUint32 - 1},
- },
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- {
- name: "NotEqual",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- NotEqual(0x7aabbccdd),
- NotEqual(math.MaxUint64 - 1),
- NotEqual(math.MaxUint32),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "arg allowed",
- data: linux.SeccompData{
- Nr: 1,
- Arch: LINUX_AUDIT_ARCH,
- Args: [6]uint64{0, math.MaxUint64, math.MaxUint32 - 1},
- },
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "arg disallowed (one equal)",
- data: linux.SeccompData{
- Nr: 1,
- Arch: LINUX_AUDIT_ARCH,
- Args: [6]uint64{0x7aabbccdd, math.MaxUint64, math.MaxUint32 - 1},
- },
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg disallowed (all equal)",
- data: linux.SeccompData{
- Nr: 1,
- Arch: LINUX_AUDIT_ARCH,
- Args: [6]uint64{0x7aabbccdd, math.MaxUint64 - 1, math.MaxUint32},
- },
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- {
- name: "GreaterThan",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- // 4294967298
- // Both upper 32 bits and lower 32 bits are non-zero.
- // 00000000000000000000000000000010
- // 00000000000000000000000000000010
- GreaterThan(0x00000002_00000002),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "high 32bits greater",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000003_00000002}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "high 32bits equal, low 32bits greater",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000002_00000003}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "high 32bits equal, low 32bits equal",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000002_00000002}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "high 32bits equal, low 32bits less",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000002_00000001}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "high 32bits less",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000001_00000003}},
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- {
- name: "GreaterThan (multi)",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- GreaterThan(0xf),
- GreaterThan(0xabcd000d),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "arg allowed",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x10, 0xffffffff}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "arg disallowed (first arg equal)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0xf, 0xffffffff}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg disallowed (first arg smaller)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x0, 0xffffffff}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg disallowed (second arg equal)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x10, 0xabcd000d}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg disallowed (second arg smaller)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x10, 0xa000ffff}},
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- {
- name: "GreaterThanOrEqual",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- // 4294967298
- // Both upper 32 bits and lower 32 bits are non-zero.
- // 00000000000000000000000000000010
- // 00000000000000000000000000000010
- GreaterThanOrEqual(0x00000002_00000002),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "high 32bits greater",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000003_00000002}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "high 32bits equal, low 32bits greater",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000002_00000003}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "high 32bits equal, low 32bits equal",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000002_00000002}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "high 32bits equal, low 32bits less",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000002_00000001}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "high 32bits less",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000001_00000002}},
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- {
- name: "GreaterThanOrEqual (multi)",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- GreaterThanOrEqual(0xf),
- GreaterThanOrEqual(0xabcd000d),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "arg allowed (both greater)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x10, 0xffffffff}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "arg allowed (first arg equal)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0xf, 0xffffffff}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "arg disallowed (first arg smaller)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x0, 0xffffffff}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg allowed (second arg equal)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x10, 0xabcd000d}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "arg disallowed (second arg smaller)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x10, 0xa000ffff}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg disallowed (both arg smaller)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x0, 0xa000ffff}},
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- {
- name: "LessThan",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- // 4294967298
- // Both upper 32 bits and lower 32 bits are non-zero.
- // 00000000000000000000000000000010
- // 00000000000000000000000000000010
- LessThan(0x00000002_00000002),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "high 32bits greater",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000003_00000002}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "high 32bits equal, low 32bits greater",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000002_00000003}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "high 32bits equal, low 32bits equal",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000002_00000002}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "high 32bits equal, low 32bits less",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000002_00000001}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "high 32bits less",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000001_00000002}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- },
- },
- {
- name: "LessThan (multi)",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- LessThan(0x1),
- LessThan(0xabcd000d),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "arg allowed",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x0, 0x0}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "arg disallowed (first arg equal)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x1, 0x0}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg disallowed (first arg greater)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x2, 0x0}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg disallowed (second arg equal)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x0, 0xabcd000d}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg disallowed (second arg greater)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x0, 0xffffffff}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg disallowed (both arg greater)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x2, 0xffffffff}},
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- {
- name: "LessThanOrEqual",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- // 4294967298
- // Both upper 32 bits and lower 32 bits are non-zero.
- // 00000000000000000000000000000010
- // 00000000000000000000000000000010
- LessThanOrEqual(0x00000002_00000002),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "high 32bits greater",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000003_00000002}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "high 32bits equal, low 32bits greater",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000002_00000003}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "high 32bits equal, low 32bits equal",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000002_00000002}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "high 32bits equal, low 32bits less",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000002_00000001}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "high 32bits less",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x00000001_00000002}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- },
- },
-
- {
- name: "LessThanOrEqual (multi)",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- LessThanOrEqual(0x1),
- LessThanOrEqual(0xabcd000d),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "arg allowed",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x0, 0x0}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "arg allowed (first arg equal)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x1, 0x0}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "arg disallowed (first arg greater)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x2, 0x0}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg allowed (second arg equal)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x0, 0xabcd000d}},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "arg disallowed (second arg greater)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x0, 0xffffffff}},
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg disallowed (both arg greater)",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0x2, 0xffffffff}},
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- {
- name: "MaskedEqual",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- // x & 00000001 00000011 (0x103) == 00000000 00000001 (0x1)
- // Input x must have lowest order bit set and
- // must *not* have 8th or second lowest order bit set.
- MaskedEqual(0x103, 0x1),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "arg allowed (low order mandatory bit)",
- data: linux.SeccompData{
- Nr: 1,
- Arch: LINUX_AUDIT_ARCH,
- // 00000000 00000000 00000000 00000001
- Args: [6]uint64{0x1},
- },
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "arg allowed (low order optional bit)",
- data: linux.SeccompData{
- Nr: 1,
- Arch: LINUX_AUDIT_ARCH,
- // 00000000 00000000 00000000 00000101
- Args: [6]uint64{0x5},
- },
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "arg disallowed (lowest order bit not set)",
- data: linux.SeccompData{
- Nr: 1,
- Arch: LINUX_AUDIT_ARCH,
- // 00000000 00000000 00000000 00000010
- Args: [6]uint64{0x2},
- },
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg disallowed (second lowest order bit set)",
- data: linux.SeccompData{
- Nr: 1,
- Arch: LINUX_AUDIT_ARCH,
- // 00000000 00000000 00000000 00000011
- Args: [6]uint64{0x3},
- },
- want: linux.SECCOMP_RET_TRAP,
- },
- {
- desc: "arg disallowed (8th bit set)",
- data: linux.SeccompData{
- Nr: 1,
- Arch: LINUX_AUDIT_ARCH,
- // 00000000 00000000 00000001 00000000
- Args: [6]uint64{0x100},
- },
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- {
- name: "Instruction Pointer",
- ruleSets: []RuleSet{
- {
- Rules: SyscallRules{
- 1: []Rule{
- {
- RuleIP: EqualTo(0x7aabbccdd),
- },
- },
- },
- Action: linux.SECCOMP_RET_ALLOW,
- },
- },
- defaultAction: linux.SECCOMP_RET_TRAP,
- badArchAction: linux.SECCOMP_RET_KILL_THREAD,
- specs: []spec{
- {
- desc: "allowed",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{}, InstructionPointer: 0x7aabbccdd},
- want: linux.SECCOMP_RET_ALLOW,
- },
- {
- desc: "disallowed",
- data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{}, InstructionPointer: 0x711223344},
- want: linux.SECCOMP_RET_TRAP,
- },
- },
- },
- } {
- t.Run(test.name, func(t *testing.T) {
- instrs, err := BuildProgram(test.ruleSets, test.defaultAction, test.badArchAction)
- if err != nil {
- t.Fatalf("BuildProgram() got error: %v", err)
- }
- p, err := bpf.Compile(instrs)
- if err != nil {
- t.Fatalf("bpf.Compile() got error: %v", err)
- }
- for _, spec := range test.specs {
- got, err := bpf.Exec(p, dataAsInput(&spec.data))
- if err != nil {
- t.Fatalf("%s: bpf.Exec() got error: %v", spec.desc, err)
- }
- if got != uint32(spec.want) {
- // Include a decoded version of the program in output for debugging purposes.
- decoded, _ := bpf.DecodeInstructions(instrs)
- t.Fatalf("%s: got: %d, want: %d\nBPF Program\n%s", spec.desc, got, spec.want, decoded)
- }
- }
- })
- }
-}
-
-// TestRandom tests that randomly generated rules are encoded correctly.
-func TestRandom(t *testing.T) {
- rand.Seed(time.Now().UnixNano())
- size := rand.Intn(50) + 1
- syscallRules := make(map[uintptr][]Rule)
- for len(syscallRules) < size {
- n := uintptr(rand.Intn(200))
- if _, ok := syscallRules[n]; !ok {
- syscallRules[n] = []Rule{}
- }
- }
-
- t.Logf("Testing filters: %v", syscallRules)
- instrs, err := BuildProgram([]RuleSet{
- {
- Rules: syscallRules,
- Action: linux.SECCOMP_RET_ALLOW,
- },
- }, linux.SECCOMP_RET_TRAP, linux.SECCOMP_RET_KILL_THREAD)
- if err != nil {
- t.Fatalf("buildProgram() got error: %v", err)
- }
- p, err := bpf.Compile(instrs)
- if err != nil {
- t.Fatalf("bpf.Compile() got error: %v", err)
- }
- for i := uint32(0); i < 200; i++ {
- data := linux.SeccompData{Nr: int32(i), Arch: LINUX_AUDIT_ARCH}
- got, err := bpf.Exec(p, dataAsInput(&data))
- if err != nil {
- t.Errorf("bpf.Exec() got error: %v, for syscall %d", err, i)
- continue
- }
- want := linux.SECCOMP_RET_TRAP
- if _, ok := syscallRules[uintptr(i)]; ok {
- want = linux.SECCOMP_RET_ALLOW
- }
- if got != uint32(want) {
- t.Errorf("bpf.Exec() = %d, want: %d, for syscall %d", got, want, i)
- }
- }
-}
-
-// TestReadDeal checks that a process dies when it trips over the filter and
-// that it doesn't die when the filter is not triggered.
-func TestRealDeal(t *testing.T) {
- for _, test := range []struct {
- die bool
- want string
- }{
- {die: true, want: "bad system call"},
- {die: false, want: "Syscall was allowed!!!"},
- } {
- victim, err := newVictim()
- if err != nil {
- t.Fatalf("unable to get victim: %v", err)
- }
- defer os.Remove(victim)
- dieFlag := fmt.Sprintf("-die=%v", test.die)
- cmd := exec.Command(victim, dieFlag)
-
- out, err := cmd.CombinedOutput()
- if test.die {
- if err == nil {
- t.Errorf("victim was not killed as expected, output: %s", out)
- continue
- }
- // Depending on kernel version, either RET_TRAP or RET_KILL_PROCESS is
- // used. RET_TRAP dumps reason for exit in output, while RET_KILL_PROCESS
- // returns SIGSYS as exit status.
- if !strings.Contains(string(out), test.want) &&
- !strings.Contains(err.Error(), test.want) {
- t.Errorf("Victim error is wrong, got: %v, err: %v, want: %v", string(out), err, test.want)
- continue
- }
- } else {
- if err != nil {
- t.Errorf("victim failed to execute, err: %v", err)
- continue
- }
- if !strings.Contains(string(out), test.want) {
- t.Errorf("Victim output is wrong, got: %v, want: %v", string(out), test.want)
- continue
- }
- }
- }
-}
-
-// TestMerge ensures that empty rules are not erased when rules are merged.
-func TestMerge(t *testing.T) {
- for _, tst := range []struct {
- name string
- main []Rule
- merge []Rule
- want []Rule
- }{
- {
- name: "empty both",
- main: nil,
- merge: nil,
- want: []Rule{{}, {}},
- },
- {
- name: "empty main",
- main: nil,
- merge: []Rule{{}},
- want: []Rule{{}, {}},
- },
- {
- name: "empty merge",
- main: []Rule{{}},
- merge: nil,
- want: []Rule{{}, {}},
- },
- } {
- t.Run(tst.name, func(t *testing.T) {
- mainRules := SyscallRules{1: tst.main}
- mergeRules := SyscallRules{1: tst.merge}
- mainRules.Merge(mergeRules)
- if got, want := len(mainRules[1]), len(tst.want); got != want {
- t.Errorf("wrong length, got: %d, want: %d", got, want)
- }
- for i, r := range mainRules[1] {
- if r != tst.want[i] {
- t.Errorf("result, got: %v, want: %v", r, tst.want[i])
- }
- }
- })
- }
-}
-
-// TestAddRule ensures that empty rules are not erased when rules are added.
-func TestAddRule(t *testing.T) {
- rules := SyscallRules{1: {}}
- rules.AddRule(1, Rule{})
- if got, want := len(rules[1]), 2; got != want {
- t.Errorf("len(rules[1]), got: %d, want: %d", got, want)
- }
-}
diff --git a/pkg/seccomp/seccomp_test_victim.go b/pkg/seccomp/seccomp_test_victim.go
deleted file mode 100644
index 7f33e0d9e..000000000
--- a/pkg/seccomp/seccomp_test_victim.go
+++ /dev/null
@@ -1,116 +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.
-
-// Test binary used to test that seccomp filters are properly constructed and
-// indeed kill the process on violation.
-package main
-
-import (
- "flag"
- "fmt"
- "os"
- "syscall"
-
- "gvisor.dev/gvisor/pkg/seccomp"
-)
-
-func main() {
- dieFlag := flag.Bool("die", false, "trips over the filter if true")
- flag.Parse()
-
- syscalls := seccomp.SyscallRules{
- syscall.SYS_ACCEPT: {},
- syscall.SYS_BIND: {},
- syscall.SYS_BRK: {},
- syscall.SYS_CLOCK_GETTIME: {},
- syscall.SYS_CLONE: {},
- syscall.SYS_CLOSE: {},
- syscall.SYS_DUP: {},
- syscall.SYS_DUP3: {},
- syscall.SYS_EPOLL_CREATE1: {},
- syscall.SYS_EPOLL_CTL: {},
- syscall.SYS_EPOLL_PWAIT: {},
- syscall.SYS_EXIT: {},
- syscall.SYS_EXIT_GROUP: {},
- syscall.SYS_FALLOCATE: {},
- syscall.SYS_FCHMOD: {},
- syscall.SYS_FCNTL: {},
- syscall.SYS_FSTAT: {},
- syscall.SYS_FSYNC: {},
- syscall.SYS_FTRUNCATE: {},
- syscall.SYS_FUTEX: {},
- syscall.SYS_GETDENTS64: {},
- syscall.SYS_GETPEERNAME: {},
- syscall.SYS_GETPID: {},
- syscall.SYS_GETSOCKNAME: {},
- syscall.SYS_GETSOCKOPT: {},
- syscall.SYS_GETTID: {},
- syscall.SYS_GETTIMEOFDAY: {},
- syscall.SYS_LISTEN: {},
- syscall.SYS_LSEEK: {},
- syscall.SYS_MADVISE: {},
- syscall.SYS_MINCORE: {},
- syscall.SYS_MMAP: {},
- syscall.SYS_MPROTECT: {},
- syscall.SYS_MUNLOCK: {},
- syscall.SYS_MUNMAP: {},
- syscall.SYS_NANOSLEEP: {},
- syscall.SYS_PPOLL: {},
- syscall.SYS_PREAD64: {},
- syscall.SYS_PSELECT6: {},
- syscall.SYS_PWRITE64: {},
- syscall.SYS_READ: {},
- syscall.SYS_READLINKAT: {},
- syscall.SYS_READV: {},
- syscall.SYS_RECVMSG: {},
- syscall.SYS_RENAMEAT: {},
- syscall.SYS_RESTART_SYSCALL: {},
- syscall.SYS_RT_SIGACTION: {},
- syscall.SYS_RT_SIGPROCMASK: {},
- syscall.SYS_RT_SIGRETURN: {},
- syscall.SYS_SCHED_YIELD: {},
- syscall.SYS_SENDMSG: {},
- syscall.SYS_SETITIMER: {},
- syscall.SYS_SET_ROBUST_LIST: {},
- syscall.SYS_SETSOCKOPT: {},
- syscall.SYS_SHUTDOWN: {},
- syscall.SYS_SIGALTSTACK: {},
- syscall.SYS_SOCKET: {},
- syscall.SYS_SYNC_FILE_RANGE: {},
- syscall.SYS_TGKILL: {},
- syscall.SYS_UTIMENSAT: {},
- syscall.SYS_WRITE: {},
- syscall.SYS_WRITEV: {},
- }
-
- arch_syscalls(syscalls)
-
- die := *dieFlag
- if !die {
- syscalls[syscall.SYS_OPENAT] = []seccomp.Rule{
- {
- seccomp.EqualTo(10),
- },
- }
- }
-
- if err := seccomp.Install(syscalls); err != nil {
- fmt.Printf("Failed to install seccomp: %v", err)
- os.Exit(1)
- }
- fmt.Printf("Filters installed\n")
-
- syscall.RawSyscall(syscall.SYS_OPENAT, 10, 0, 0)
- fmt.Printf("Syscall was allowed!!!\n")
-}
diff --git a/pkg/seccomp/seccomp_test_victim_amd64.go b/pkg/seccomp/seccomp_test_victim_amd64.go
deleted file mode 100644
index 5dfc68e25..000000000
--- a/pkg/seccomp/seccomp_test_victim_amd64.go
+++ /dev/null
@@ -1,32 +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.
-
-// Test binary used to test that seccomp filters are properly constructed and
-// indeed kill the process on violation.
-
-// +build amd64
-
-package main
-
-import (
- "gvisor.dev/gvisor/pkg/seccomp"
- "syscall"
-)
-
-func arch_syscalls(syscalls seccomp.SyscallRules) {
- syscalls[syscall.SYS_ARCH_PRCTL] = []seccomp.Rule{}
- syscalls[syscall.SYS_EPOLL_WAIT] = []seccomp.Rule{}
- syscalls[syscall.SYS_NEWFSTATAT] = []seccomp.Rule{}
- syscalls[syscall.SYS_OPEN] = []seccomp.Rule{}
-}
diff --git a/pkg/seccomp/seccomp_test_victim_arm64.go b/pkg/seccomp/seccomp_test_victim_arm64.go
deleted file mode 100644
index 5184d8ac4..000000000
--- a/pkg/seccomp/seccomp_test_victim_arm64.go
+++ /dev/null
@@ -1,29 +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.
-
-// Test binary used to test that seccomp filters are properly constructed and
-// indeed kill the process on violation.
-
-// +build arm64
-
-package main
-
-import (
- "gvisor.dev/gvisor/pkg/seccomp"
- "syscall"
-)
-
-func arch_syscalls(syscalls seccomp.SyscallRules) {
- syscalls[syscall.SYS_FSTATAT] = []seccomp.Rule{}
-}
diff --git a/pkg/seccomp/seccomp_unsafe_state_autogen.go b/pkg/seccomp/seccomp_unsafe_state_autogen.go
new file mode 100644
index 000000000..e16b5d7c2
--- /dev/null
+++ b/pkg/seccomp/seccomp_unsafe_state_autogen.go
@@ -0,0 +1,3 @@
+// automatically generated by stateify.
+
+package seccomp