diff options
Diffstat (limited to 'pkg/seccomp')
-rw-r--r-- | pkg/seccomp/BUILD | 59 | ||||
-rw-r--r-- | pkg/seccomp/seccomp_amd64_state_autogen.go | 5 | ||||
-rw-r--r-- | pkg/seccomp/seccomp_arm64_state_autogen.go | 5 | ||||
-rw-r--r-- | pkg/seccomp/seccomp_state_autogen.go | 3 | ||||
-rw-r--r-- | pkg/seccomp/seccomp_test.go | 1059 | ||||
-rw-r--r-- | pkg/seccomp/seccomp_test_victim.go | 116 | ||||
-rw-r--r-- | pkg/seccomp/seccomp_test_victim_amd64.go | 32 | ||||
-rw-r--r-- | pkg/seccomp/seccomp_test_victim_arm64.go | 29 | ||||
-rw-r--r-- | pkg/seccomp/seccomp_unsafe_state_autogen.go | 3 |
9 files changed, 16 insertions, 1295 deletions
diff --git a/pkg/seccomp/BUILD b/pkg/seccomp/BUILD deleted file mode 100644 index 201dd072f..000000000 --- a/pkg/seccomp/BUILD +++ /dev/null @@ -1,59 +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", - "@org_golang_x_sys//unix:go_default_library", - ], -) - -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", - "@org_golang_x_sys//unix:go_default_library", - ], -) - -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 a96b1e327..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" - - "golang.org/x/sys/unix" - "gvisor.dev/gvisor/pkg/seccomp" -) - -func main() { - dieFlag := flag.Bool("die", false, "trips over the filter if true") - flag.Parse() - - syscalls := seccomp.SyscallRules{ - unix.SYS_ACCEPT: {}, - unix.SYS_BIND: {}, - unix.SYS_BRK: {}, - unix.SYS_CLOCK_GETTIME: {}, - unix.SYS_CLONE: {}, - unix.SYS_CLOSE: {}, - unix.SYS_DUP: {}, - unix.SYS_DUP3: {}, - unix.SYS_EPOLL_CREATE1: {}, - unix.SYS_EPOLL_CTL: {}, - unix.SYS_EPOLL_PWAIT: {}, - unix.SYS_EXIT: {}, - unix.SYS_EXIT_GROUP: {}, - unix.SYS_FALLOCATE: {}, - unix.SYS_FCHMOD: {}, - unix.SYS_FCNTL: {}, - unix.SYS_FSTAT: {}, - unix.SYS_FSYNC: {}, - unix.SYS_FTRUNCATE: {}, - unix.SYS_FUTEX: {}, - unix.SYS_GETDENTS64: {}, - unix.SYS_GETPEERNAME: {}, - unix.SYS_GETPID: {}, - unix.SYS_GETSOCKNAME: {}, - unix.SYS_GETSOCKOPT: {}, - unix.SYS_GETTID: {}, - unix.SYS_GETTIMEOFDAY: {}, - unix.SYS_LISTEN: {}, - unix.SYS_LSEEK: {}, - unix.SYS_MADVISE: {}, - unix.SYS_MINCORE: {}, - unix.SYS_MMAP: {}, - unix.SYS_MPROTECT: {}, - unix.SYS_MUNLOCK: {}, - unix.SYS_MUNMAP: {}, - unix.SYS_NANOSLEEP: {}, - unix.SYS_PPOLL: {}, - unix.SYS_PREAD64: {}, - unix.SYS_PSELECT6: {}, - unix.SYS_PWRITE64: {}, - unix.SYS_READ: {}, - unix.SYS_READLINKAT: {}, - unix.SYS_READV: {}, - unix.SYS_RECVMSG: {}, - unix.SYS_RENAMEAT: {}, - unix.SYS_RESTART_SYSCALL: {}, - unix.SYS_RT_SIGACTION: {}, - unix.SYS_RT_SIGPROCMASK: {}, - unix.SYS_RT_SIGRETURN: {}, - unix.SYS_SCHED_YIELD: {}, - unix.SYS_SENDMSG: {}, - unix.SYS_SETITIMER: {}, - unix.SYS_SET_ROBUST_LIST: {}, - unix.SYS_SETSOCKOPT: {}, - unix.SYS_SHUTDOWN: {}, - unix.SYS_SIGALTSTACK: {}, - unix.SYS_SOCKET: {}, - unix.SYS_SYNC_FILE_RANGE: {}, - unix.SYS_TGKILL: {}, - unix.SYS_UTIMENSAT: {}, - unix.SYS_WRITE: {}, - unix.SYS_WRITEV: {}, - } - - arch_syscalls(syscalls) - - die := *dieFlag - if !die { - syscalls[unix.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") - - unix.RawSyscall(unix.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 efb8604ec..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 ( - "golang.org/x/sys/unix" - "gvisor.dev/gvisor/pkg/seccomp" -) - -func arch_syscalls(syscalls seccomp.SyscallRules) { - syscalls[unix.SYS_ARCH_PRCTL] = []seccomp.Rule{} - syscalls[unix.SYS_EPOLL_WAIT] = []seccomp.Rule{} - syscalls[unix.SYS_NEWFSTATAT] = []seccomp.Rule{} - syscalls[unix.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 97cb5f5fe..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 ( - "golang.org/x/sys/unix" - "gvisor.dev/gvisor/pkg/seccomp" -) - -func arch_syscalls(syscalls seccomp.SyscallRules) { - syscalls[unix.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 |