mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Refactor seccomp rules with interfaces rather than disjunctive normal form.
This replaces the `seccomp.Rule` type with the `seccomp.SyscallRule`
interface, which is an abstraction that defines how to match a syscall's
arguments and RIP.
This has the following benefits:
- The code can verify that rules are self-contained, as the
`SyscallRule.Render` contract specifies that the rule must jump to
either a "matched" or "not matched" label, and may not fall through.
It uses `ProgramBuilder`'s support for asserting unreachability to
enforce this.
- Rules that match everything are more explicit (no more implicit
"no rules means everything matches" behavior, instead you have to
explicitly specify `seccomp.MatchAll{}`).
- "OR" behavior is explicit (a disjunctive rule is marked as `seccomp.Or`
rather than the current implicit meaning of a list of rules).
- Allows the creation of more sophisticated matching rules that don't work
on a per-argument basis. This change does not do any of that yet, it
simply refactors existing rules without changing the way they work.
- Decouples rule-specific rendering code from the larger program generation
code (BST, architecture check, etc.).
Unfortunately there is no easy way to split this change into multiple
sub-changes without introducing additional complexity to support both forms
of expressing rules, so sorry if this is a large change. But note that it
is actually net-negative in line count.
Despite the size of this change, please review it carefully, as this is a
security-sensitive change.
PiperOrigin-RevId: 571459670
This commit is contained in:
committed by
gVisor bot
parent
9cb26fd34f
commit
addac5f248
+205
-290
File diff suppressed because it is too large
Load Diff
+313
-53
@@ -16,8 +16,12 @@ package seccomp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/bpf"
|
||||
)
|
||||
|
||||
// The offsets are based on the following struct in include/linux/seccomp.h.
|
||||
@@ -47,49 +51,49 @@ func seccompDataOffsetArgHigh(i int) uint32 {
|
||||
// AnyValue is marker to indicate any value will be accepted.
|
||||
type AnyValue struct{}
|
||||
|
||||
func (a AnyValue) String() (s string) {
|
||||
func (AnyValue) String() string {
|
||||
return "*"
|
||||
}
|
||||
|
||||
// EqualTo specifies a value that needs to be strictly matched.
|
||||
type EqualTo uintptr
|
||||
|
||||
func (a EqualTo) String() (s string) {
|
||||
func (a EqualTo) String() string {
|
||||
return fmt.Sprintf("== %#x", uintptr(a))
|
||||
}
|
||||
|
||||
// NotEqual specifies a value that is strictly not equal.
|
||||
type NotEqual uintptr
|
||||
|
||||
func (a NotEqual) String() (s string) {
|
||||
func (a NotEqual) String() string {
|
||||
return fmt.Sprintf("!= %#x", uintptr(a))
|
||||
}
|
||||
|
||||
// GreaterThan specifies a value that needs to be strictly smaller.
|
||||
type GreaterThan uintptr
|
||||
|
||||
func (a GreaterThan) String() (s string) {
|
||||
func (a GreaterThan) String() string {
|
||||
return fmt.Sprintf("> %#x", uintptr(a))
|
||||
}
|
||||
|
||||
// GreaterThanOrEqual specifies a value that needs to be smaller or equal.
|
||||
type GreaterThanOrEqual uintptr
|
||||
|
||||
func (a GreaterThanOrEqual) String() (s string) {
|
||||
func (a GreaterThanOrEqual) String() string {
|
||||
return fmt.Sprintf(">= %#x", uintptr(a))
|
||||
}
|
||||
|
||||
// LessThan specifies a value that needs to be strictly greater.
|
||||
type LessThan uintptr
|
||||
|
||||
func (a LessThan) String() (s string) {
|
||||
func (a LessThan) String() string {
|
||||
return fmt.Sprintf("< %#x", uintptr(a))
|
||||
}
|
||||
|
||||
// LessThanOrEqual specifies a value that needs to be greater or equal.
|
||||
type LessThanOrEqual uintptr
|
||||
|
||||
func (a LessThanOrEqual) String() (s string) {
|
||||
func (a LessThanOrEqual) String() string {
|
||||
return fmt.Sprintf("<= %#x", uintptr(a))
|
||||
}
|
||||
|
||||
@@ -98,7 +102,7 @@ type maskedEqual struct {
|
||||
value uintptr
|
||||
}
|
||||
|
||||
func (a maskedEqual) String() (s string) {
|
||||
func (a maskedEqual) String() string {
|
||||
return fmt.Sprintf("& %#x == %#x", a.mask, a.value)
|
||||
}
|
||||
|
||||
@@ -112,25 +116,277 @@ func MaskedEqual(mask, value uintptr) any {
|
||||
}
|
||||
}
|
||||
|
||||
// Rule stores the allowed syscall arguments.
|
||||
// SyscallRule expresses a set of rules to verify the arguments of a specific
|
||||
// syscall.
|
||||
type SyscallRule interface {
|
||||
// Render renders the syscall rule in the given `program`.
|
||||
// The emitted instructions **must** end up jumping to either
|
||||
// `labelSet.Matched()` or `labelSet.Mismatched()`; they may
|
||||
// not "fall through" to whatever instructions will be added
|
||||
// next into the program.
|
||||
Render(program *syscallProgram, labelSet *labelSet)
|
||||
|
||||
// String returns a human-readable string representing what the rule does.
|
||||
String() string
|
||||
}
|
||||
|
||||
// MatchAll implements `SyscallRule` and matches everything.
|
||||
type MatchAll struct{}
|
||||
|
||||
// Render implements `SyscallRule.Render`.
|
||||
func (MatchAll) Render(program *syscallProgram, labelSet *labelSet) {
|
||||
program.JumpTo(labelSet.Matched())
|
||||
}
|
||||
|
||||
// String implements `SyscallRule.String`.
|
||||
func (MatchAll) String() string { return "true" }
|
||||
|
||||
// Or expresses an "OR" (a disjunction) over a set of `SyscallRule`s.
|
||||
// If an Or is empty, it will not match anything.
|
||||
type Or []SyscallRule
|
||||
|
||||
// Render implements `SyscallRule.Render`.
|
||||
func (or Or) Render(program *syscallProgram, labelSet *labelSet) {
|
||||
// If `len(or) == 1`, this will be optimized away to be the same as
|
||||
// rendering the single rule in the disjunction.
|
||||
for i, rule := range or {
|
||||
frag := program.Record()
|
||||
nextRuleLabel := labelSet.NewLabel()
|
||||
rule.Render(program, labelSet.Push(fmt.Sprintf("or[%d]", i), labelSet.Matched(), nextRuleLabel))
|
||||
frag.MustHaveJumpedTo(labelSet.Matched(), nextRuleLabel)
|
||||
program.Label(nextRuleLabel)
|
||||
}
|
||||
program.JumpTo(labelSet.Mismatched())
|
||||
}
|
||||
|
||||
// String implements `SyscallRule.String`.
|
||||
func (or Or) String() string {
|
||||
switch len(or) {
|
||||
case 0:
|
||||
return "false"
|
||||
case 1:
|
||||
return or[0].String()
|
||||
default:
|
||||
var sb strings.Builder
|
||||
sb.WriteRune('(')
|
||||
for i, rule := range or {
|
||||
if i != 0 {
|
||||
sb.WriteString(" || ")
|
||||
}
|
||||
sb.WriteString(rule.String())
|
||||
}
|
||||
sb.WriteRune(')')
|
||||
return sb.String()
|
||||
}
|
||||
}
|
||||
|
||||
// merge merges `rule1` and `rule2`, simplifying `MatchAll` and `Or` rules.
|
||||
func merge(rule1, rule2 SyscallRule) SyscallRule {
|
||||
_, rule1IsMatchAll := rule1.(MatchAll)
|
||||
_, rule2IsMatchAll := rule2.(MatchAll)
|
||||
if rule1IsMatchAll || rule2IsMatchAll {
|
||||
return MatchAll{}
|
||||
}
|
||||
rule1Or, rule1IsOr := rule1.(Or)
|
||||
rule2Or, rule2IsOr := rule2.(Or)
|
||||
if rule1IsOr && rule2IsOr {
|
||||
return append(rule1Or, rule2Or...)
|
||||
}
|
||||
if rule1IsOr {
|
||||
return append(rule1Or, rule2)
|
||||
}
|
||||
if rule2IsOr {
|
||||
return append(rule2Or, rule1)
|
||||
}
|
||||
return Or{rule1, rule2}
|
||||
}
|
||||
|
||||
// PerArg implements SyscallRule and verifies the syscall arguments and RIP.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// rule := Rule {
|
||||
// rule := PerArg{
|
||||
// EqualTo(linux.ARCH_GET_FS | linux.ARCH_SET_FS), // arg0
|
||||
// }
|
||||
type Rule [7]any // 6 arguments + RIP
|
||||
type PerArg [7]any // 6 arguments + RIP
|
||||
|
||||
// RuleIP indicates what rules in the Rule array have to be applied to
|
||||
// instruction pointer.
|
||||
const RuleIP = 6
|
||||
|
||||
func (r Rule) String() (s string) {
|
||||
if len(r) == 0 {
|
||||
// Render implements `SyscallRule.Render`.
|
||||
func (pa PerArg) Render(program *syscallProgram, labelSet *labelSet) {
|
||||
for i, arg := range pa {
|
||||
if arg == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
frag := program.Record()
|
||||
nextArgLabel := labelSet.NewLabel()
|
||||
labelSuffix := fmt.Sprintf("arg[%d]", i)
|
||||
// Determine the data offset for low and high bits of input.
|
||||
dataOffsetLow := seccompDataOffsetArgLow(i)
|
||||
dataOffsetHigh := seccompDataOffsetArgHigh(i)
|
||||
if i == RuleIP {
|
||||
dataOffsetLow = seccompDataOffsetIPLow
|
||||
dataOffsetHigh = seccompDataOffsetIPHigh
|
||||
labelSuffix = "rip"
|
||||
}
|
||||
ls := labelSet.Push(labelSuffix, nextArgLabel, labelSet.Mismatched())
|
||||
|
||||
// Add the conditional operation. Input values to the BPF
|
||||
// program are 64bit values. However, comparisons in BPF can
|
||||
// only be done on 32bit values. This means that we need to
|
||||
// operate on each 32bit half in order to do one logical 64bit
|
||||
// comparison.
|
||||
switch a := arg.(type) {
|
||||
case AnyValue:
|
||||
program.JumpTo(ls.Matched())
|
||||
case EqualTo:
|
||||
// EqualTo checks that both the higher and lower 32bits are equal.
|
||||
high, low := uint32(a>>32), uint32(a)
|
||||
|
||||
// Assert that the lower 32bits are equal.
|
||||
// arg_low == low ? continue : violation
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetLow)
|
||||
program.IfNot(bpf.Jmp|bpf.Jeq|bpf.K, low, ls.Mismatched())
|
||||
|
||||
// Assert that the higher 32bits are also equal.
|
||||
// arg_high == high ? continue/success : violation
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetHigh)
|
||||
program.IfNot(bpf.Jmp|bpf.Jeq|bpf.K, high, ls.Mismatched())
|
||||
program.JumpTo(ls.Matched())
|
||||
case NotEqual:
|
||||
// NotEqual checks that either the higher or lower 32bits
|
||||
// are *not* equal.
|
||||
high, low := uint32(a>>32), uint32(a)
|
||||
|
||||
// Check if the higher 32bits are (not) equal.
|
||||
// arg_low != low ? success : continue
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetLow)
|
||||
program.IfNot(bpf.Jmp|bpf.Jeq|bpf.K, low, ls.Matched())
|
||||
|
||||
// Assert that the lower 32bits are not equal (assuming
|
||||
// higher bits are equal).
|
||||
// arg_high != high ? success : violation
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetHigh)
|
||||
program.IfNot(bpf.Jmp|bpf.Jeq|bpf.K, high, ls.Matched())
|
||||
program.JumpTo(ls.Mismatched())
|
||||
case GreaterThan:
|
||||
// GreaterThan checks that the higher 32bits is greater
|
||||
// *or* that the higher 32bits are equal and the lower
|
||||
// 32bits are greater.
|
||||
high, low := uint32(a>>32), uint32(a)
|
||||
|
||||
// Assert the higher 32bits are greater than or equal.
|
||||
// arg_high >= high ? continue : violation (arg_high < high)
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetHigh)
|
||||
program.IfNot(bpf.Jmp|bpf.Jge|bpf.K, high, ls.Mismatched())
|
||||
|
||||
// Assert that the lower 32bits are greater.
|
||||
// arg_high == high ? continue : success (arg_high > high)
|
||||
program.IfNot(bpf.Jmp|bpf.Jeq|bpf.K, high, ls.Matched())
|
||||
// arg_low > low ? continue/success : violation (arg_high == high and arg_low <= low)
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetLow)
|
||||
program.IfNot(bpf.Jmp|bpf.Jgt|bpf.K, low, ls.Mismatched())
|
||||
program.JumpTo(ls.Matched())
|
||||
case GreaterThanOrEqual:
|
||||
// GreaterThanOrEqual checks that the higher 32bits is
|
||||
// greater *or* that the higher 32bits are equal and the
|
||||
// lower 32bits are greater than or equal.
|
||||
high, low := uint32(a>>32), uint32(a)
|
||||
|
||||
// Assert the higher 32bits are greater than or equal.
|
||||
// arg_high >= high ? continue : violation (arg_high < high)
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetHigh)
|
||||
program.IfNot(bpf.Jmp|bpf.Jge|bpf.K, high, ls.Mismatched())
|
||||
// arg_high == high ? continue : success (arg_high > high)
|
||||
program.IfNot(bpf.Jmp|bpf.Jeq|bpf.K, high, ls.Matched())
|
||||
|
||||
// Assert that the lower 32bits are greater (assuming the
|
||||
// higher bits are equal).
|
||||
// arg_low >= low ? continue/success : violation (arg_high == high and arg_low < low)
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetLow)
|
||||
program.IfNot(bpf.Jmp|bpf.Jge|bpf.K, low, ls.Mismatched())
|
||||
program.JumpTo(ls.Matched())
|
||||
case LessThan:
|
||||
// LessThan checks that the higher 32bits is less *or* that
|
||||
// the higher 32bits are equal and the lower 32bits are
|
||||
// less.
|
||||
high, low := uint32(a>>32), uint32(a)
|
||||
|
||||
// Assert the higher 32bits are less than or equal.
|
||||
// arg_high > high ? violation : continue
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetHigh)
|
||||
program.If(bpf.Jmp|bpf.Jgt|bpf.K, high, ls.Mismatched())
|
||||
// arg_high == high ? continue : success (arg_high < high)
|
||||
program.IfNot(bpf.Jmp|bpf.Jeq|bpf.K, high, ls.Matched())
|
||||
|
||||
// Assert that the lower 32bits are less (assuming the
|
||||
// higher bits are equal).
|
||||
// arg_low >= low ? violation : continue
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetLow)
|
||||
program.If(bpf.Jmp|bpf.Jge|bpf.K, low, ls.Mismatched())
|
||||
program.JumpTo(ls.Matched())
|
||||
case LessThanOrEqual:
|
||||
// LessThan checks that the higher 32bits is less *or* that
|
||||
// the higher 32bits are equal and the lower 32bits are
|
||||
// less than or equal.
|
||||
high, low := uint32(a>>32), uint32(a)
|
||||
|
||||
// Assert the higher 32bits are less than or equal.
|
||||
// assert arg_high > high ? violation : continue
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetHigh)
|
||||
program.If(bpf.Jmp|bpf.Jgt|bpf.K, high, ls.Mismatched())
|
||||
// arg_high == high ? continue : success
|
||||
program.IfNot(bpf.Jmp|bpf.Jeq|bpf.K, high, ls.Matched())
|
||||
|
||||
// Assert the lower bits are less than or equal (assuming
|
||||
// the higher bits are equal).
|
||||
// arg_low > low ? violation : success
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetLow)
|
||||
program.If(bpf.Jmp|bpf.Jgt|bpf.K, low, ls.Mismatched())
|
||||
program.JumpTo(ls.Matched())
|
||||
case maskedEqual:
|
||||
// MaskedEqual checks that the bitwise AND of the value and
|
||||
// mask are equal for both the higher and lower 32bits.
|
||||
high, low := uint32(a.value>>32), uint32(a.value)
|
||||
maskHigh, maskLow := uint32(a.mask>>32), uint32(a.mask)
|
||||
|
||||
// Assert that the lower 32bits are equal when masked.
|
||||
// A <- arg_low.
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetLow)
|
||||
// A <- arg_low & maskLow
|
||||
program.Stmt(bpf.Alu|bpf.And|bpf.K, maskLow)
|
||||
// Assert that arg_low & maskLow == low.
|
||||
program.IfNot(bpf.Jmp|bpf.Jeq|bpf.K, low, ls.Mismatched())
|
||||
|
||||
// Assert that the higher 32bits are equal when masked.
|
||||
// A <- arg_high
|
||||
program.Stmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetHigh)
|
||||
// A <- arg_high & maskHigh
|
||||
program.Stmt(bpf.Alu|bpf.And|bpf.K, maskHigh)
|
||||
// Assert that arg_high & maskHigh == high.
|
||||
program.IfNot(bpf.Jmp|bpf.Jeq|bpf.K, high, ls.Mismatched())
|
||||
program.JumpTo(ls.Matched())
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown syscall rule type: %v", reflect.TypeOf(a)))
|
||||
}
|
||||
frag.MustHaveJumpedTo(ls.Matched(), ls.Mismatched())
|
||||
program.Label(nextArgLabel)
|
||||
}
|
||||
|
||||
// Matched all argument-wise rules, jump to the final rule matched label.
|
||||
program.JumpTo(labelSet.Matched())
|
||||
}
|
||||
|
||||
// String implements `SyscallRule.String`.
|
||||
func (pa PerArg) String() (s string) {
|
||||
if len(pa) == 0 {
|
||||
return
|
||||
}
|
||||
s += "( "
|
||||
for _, arg := range r {
|
||||
for _, arg := range pa {
|
||||
if arg != nil {
|
||||
s += fmt.Sprintf("%v ", arg)
|
||||
}
|
||||
@@ -139,60 +395,68 @@ func (r Rule) String() (s string) {
|
||||
return
|
||||
}
|
||||
|
||||
// SyscallRules stores a map of OR'ed argument rules indexed by the syscall number.
|
||||
// If the 'Rules' is empty, we treat it as any argument is allowed.
|
||||
// SyscallRules maps syscall numbers to their corresponding rules.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// rules := SyscallRules{
|
||||
// syscall.SYS_FUTEX: []Rule{
|
||||
// {
|
||||
// syscall.SYS_FUTEX: Or{
|
||||
// PerArg{
|
||||
// AnyValue{},
|
||||
// EqualTo(linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG),
|
||||
// }, // OR
|
||||
// {
|
||||
// },
|
||||
// PerArg{
|
||||
// AnyValue{},
|
||||
// EqualTo(linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG),
|
||||
// },
|
||||
// },
|
||||
// syscall.SYS_GETPID: []Rule{},
|
||||
// syscall.SYS_GETPID: MatchAll{},
|
||||
//
|
||||
// }
|
||||
type SyscallRules map[uintptr][]Rule
|
||||
type SyscallRules map[uintptr]SyscallRule
|
||||
|
||||
// NewSyscallRules returns a new SyscallRules.
|
||||
func NewSyscallRules() SyscallRules {
|
||||
return make(map[uintptr][]Rule)
|
||||
return make(map[uintptr]SyscallRule)
|
||||
}
|
||||
|
||||
// String returns a string representation of the syscall rules, one syscall
|
||||
// per line.
|
||||
func (sr SyscallRules) String() string {
|
||||
if len(sr) == 0 {
|
||||
return "(no rules)"
|
||||
}
|
||||
sysnums := make([]uintptr, 0, len(sr))
|
||||
for sysno := range sr {
|
||||
sysnums = append(sysnums, sysno)
|
||||
}
|
||||
sort.Slice(sysnums, func(i, j int) bool {
|
||||
return sysnums[i] < sysnums[j]
|
||||
})
|
||||
var sb strings.Builder
|
||||
for _, sysno := range sysnums {
|
||||
sb.WriteString(fmt.Sprintf("syscall %d: %v\n", sysno, sr[sysno]))
|
||||
}
|
||||
return strings.TrimSpace(sb.String())
|
||||
}
|
||||
|
||||
// AddRule adds the given rule. It will create a new entry for a new syscall, otherwise
|
||||
// it will append to the existing rules.
|
||||
func (sr SyscallRules) AddRule(sysno uintptr, r Rule) {
|
||||
func (sr SyscallRules) AddRule(sysno uintptr, r SyscallRule) {
|
||||
if cur, ok := sr[sysno]; ok {
|
||||
// An empty rules means allow all. Honor it when more rules are added.
|
||||
if len(cur) == 0 {
|
||||
sr[sysno] = append(sr[sysno], Rule{})
|
||||
}
|
||||
sr[sysno] = append(sr[sysno], r)
|
||||
sr[sysno] = merge(cur, r)
|
||||
} else {
|
||||
sr[sysno] = []Rule{r}
|
||||
sr[sysno] = r
|
||||
}
|
||||
}
|
||||
|
||||
// Merge merges the given SyscallRules.
|
||||
func (sr SyscallRules) Merge(rules SyscallRules) {
|
||||
for sysno, rs := range rules {
|
||||
func (sr SyscallRules) Merge(other SyscallRules) {
|
||||
for sysno, r := range other {
|
||||
if cur, ok := sr[sysno]; ok {
|
||||
// An empty rules means allow all. Honor it when more rules are added.
|
||||
if len(cur) == 0 {
|
||||
sr[sysno] = append(sr[sysno], Rule{})
|
||||
}
|
||||
if len(rs) == 0 {
|
||||
rs = []Rule{{}}
|
||||
}
|
||||
sr[sysno] = append(sr[sysno], rs...)
|
||||
sr[sysno] = merge(cur, r)
|
||||
} else {
|
||||
sr[sysno] = rs
|
||||
sr[sysno] = r
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,18 +464,14 @@ func (sr SyscallRules) Merge(rules SyscallRules) {
|
||||
// DenyNewExecMappings is a set of rules that denies creating new executable
|
||||
// mappings and converting existing ones.
|
||||
var DenyNewExecMappings = SyscallRules{
|
||||
unix.SYS_MMAP: []Rule{
|
||||
{
|
||||
AnyValue{},
|
||||
AnyValue{},
|
||||
MaskedEqual(unix.PROT_EXEC, unix.PROT_EXEC),
|
||||
},
|
||||
unix.SYS_MMAP: PerArg{
|
||||
AnyValue{},
|
||||
AnyValue{},
|
||||
MaskedEqual(unix.PROT_EXEC, unix.PROT_EXEC),
|
||||
},
|
||||
unix.SYS_MPROTECT: []Rule{
|
||||
{
|
||||
AnyValue{},
|
||||
AnyValue{},
|
||||
MaskedEqual(unix.PROT_EXEC, unix.PROT_EXEC),
|
||||
},
|
||||
unix.SYS_MPROTECT: PerArg{
|
||||
AnyValue{},
|
||||
AnyValue{},
|
||||
MaskedEqual(unix.PROT_EXEC, unix.PROT_EXEC),
|
||||
},
|
||||
}
|
||||
|
||||
+99
-128
@@ -24,6 +24,7 @@ import (
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -88,7 +89,7 @@ func TestBasic(t *testing.T) {
|
||||
name: "Single syscall",
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{1: {}},
|
||||
Rules: SyscallRules{1: MatchAll{}},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
},
|
||||
},
|
||||
@@ -112,18 +113,16 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
EqualTo(0x1),
|
||||
},
|
||||
1: PerArg{
|
||||
EqualTo(0x1),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
},
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: {},
|
||||
2: {},
|
||||
1: MatchAll{},
|
||||
2: MatchAll{},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_TRAP,
|
||||
},
|
||||
@@ -158,9 +157,9 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: {},
|
||||
3: {},
|
||||
5: {},
|
||||
1: MatchAll{},
|
||||
3: MatchAll{},
|
||||
5: MatchAll{},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
},
|
||||
@@ -215,7 +214,7 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: {},
|
||||
1: MatchAll{},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
},
|
||||
@@ -235,7 +234,7 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: {},
|
||||
1: MatchAll{},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
},
|
||||
@@ -255,11 +254,9 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
AnyValue{},
|
||||
EqualTo(0xf),
|
||||
},
|
||||
1: PerArg{
|
||||
AnyValue{},
|
||||
EqualTo(0xf),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
@@ -285,11 +282,11 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
1: Or{
|
||||
PerArg{
|
||||
EqualTo(0xf),
|
||||
},
|
||||
{
|
||||
PerArg{
|
||||
EqualTo(0xe),
|
||||
},
|
||||
},
|
||||
@@ -310,6 +307,11 @@ func TestBasic(t *testing.T) {
|
||||
data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0xe}},
|
||||
want: linux.SECCOMP_RET_ALLOW,
|
||||
},
|
||||
{
|
||||
desc: "match neither rule",
|
||||
data: linux.SeccompData{Nr: 1, Arch: LINUX_AUDIT_ARCH, Args: [6]uint64{0xd}},
|
||||
want: linux.SECCOMP_RET_TRAP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -317,12 +319,10 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
EqualTo(0),
|
||||
EqualTo(math.MaxUint64 - 1),
|
||||
EqualTo(math.MaxUint32),
|
||||
},
|
||||
1: PerArg{
|
||||
EqualTo(0),
|
||||
EqualTo(math.MaxUint64 - 1),
|
||||
EqualTo(math.MaxUint32),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
@@ -365,12 +365,10 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
NotEqual(0x7aabbccdd),
|
||||
NotEqual(math.MaxUint64 - 1),
|
||||
NotEqual(math.MaxUint32),
|
||||
},
|
||||
1: PerArg{
|
||||
NotEqual(0x7aabbccdd),
|
||||
NotEqual(math.MaxUint64 - 1),
|
||||
NotEqual(math.MaxUint32),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
@@ -413,14 +411,12 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
// 4294967298
|
||||
// Both upper 32 bits and lower 32 bits are non-zero.
|
||||
// 00000000000000000000000000000010
|
||||
// 00000000000000000000000000000010
|
||||
GreaterThan(0x00000002_00000002),
|
||||
},
|
||||
1: PerArg{
|
||||
// 4294967298
|
||||
// Both upper 32 bits and lower 32 bits are non-zero.
|
||||
// 00000000000000000000000000000010
|
||||
// 00000000000000000000000000000010
|
||||
GreaterThan(0x00000002_00000002),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
@@ -461,11 +457,9 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
GreaterThan(0xf),
|
||||
GreaterThan(0xabcd000d),
|
||||
},
|
||||
1: PerArg{
|
||||
GreaterThan(0xf),
|
||||
GreaterThan(0xabcd000d),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
@@ -506,14 +500,12 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
// 4294967298
|
||||
// Both upper 32 bits and lower 32 bits are non-zero.
|
||||
// 00000000000000000000000000000010
|
||||
// 00000000000000000000000000000010
|
||||
GreaterThanOrEqual(0x00000002_00000002),
|
||||
},
|
||||
1: PerArg{
|
||||
// 4294967298
|
||||
// Both upper 32 bits and lower 32 bits are non-zero.
|
||||
// 00000000000000000000000000000010
|
||||
// 00000000000000000000000000000010
|
||||
GreaterThanOrEqual(0x00000002_00000002),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
@@ -554,11 +546,9 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
GreaterThanOrEqual(0xf),
|
||||
GreaterThanOrEqual(0xabcd000d),
|
||||
},
|
||||
1: PerArg{
|
||||
GreaterThanOrEqual(0xf),
|
||||
GreaterThanOrEqual(0xabcd000d),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
@@ -604,14 +594,12 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
// 4294967298
|
||||
// Both upper 32 bits and lower 32 bits are non-zero.
|
||||
// 00000000000000000000000000000010
|
||||
// 00000000000000000000000000000010
|
||||
LessThan(0x00000002_00000002),
|
||||
},
|
||||
1: PerArg{
|
||||
// 4294967298
|
||||
// Both upper 32 bits and lower 32 bits are non-zero.
|
||||
// 00000000000000000000000000000010
|
||||
// 00000000000000000000000000000010
|
||||
LessThan(0x00000002_00000002),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
@@ -652,11 +640,9 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
LessThan(0x1),
|
||||
LessThan(0xabcd000d),
|
||||
},
|
||||
1: PerArg{
|
||||
LessThan(0x1),
|
||||
LessThan(0xabcd000d),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
@@ -702,14 +688,12 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
// 4294967298
|
||||
// Both upper 32 bits and lower 32 bits are non-zero.
|
||||
// 00000000000000000000000000000010
|
||||
// 00000000000000000000000000000010
|
||||
LessThanOrEqual(0x00000002_00000002),
|
||||
},
|
||||
1: PerArg{
|
||||
// 4294967298
|
||||
// Both upper 32 bits and lower 32 bits are non-zero.
|
||||
// 00000000000000000000000000000010
|
||||
// 00000000000000000000000000000010
|
||||
LessThanOrEqual(0x00000002_00000002),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
@@ -751,11 +735,9 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
LessThanOrEqual(0x1),
|
||||
LessThanOrEqual(0xabcd000d),
|
||||
},
|
||||
1: PerArg{
|
||||
LessThanOrEqual(0x1),
|
||||
LessThanOrEqual(0xabcd000d),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
@@ -801,13 +783,11 @@ func TestBasic(t *testing.T) {
|
||||
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),
|
||||
},
|
||||
1: PerArg{
|
||||
// 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,
|
||||
@@ -873,10 +853,8 @@ func TestBasic(t *testing.T) {
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
RuleIP: EqualTo(0x7aabbccdd),
|
||||
},
|
||||
1: PerArg{
|
||||
RuleIP: EqualTo(0x7aabbccdd),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
@@ -926,11 +904,11 @@ func TestBasic(t *testing.T) {
|
||||
func TestRandom(t *testing.T) {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
size := rand.Intn(50) + 1
|
||||
syscallRules := make(map[uintptr][]Rule)
|
||||
syscallRules := make(map[uintptr]SyscallRule)
|
||||
for len(syscallRules) < size {
|
||||
n := uintptr(rand.Intn(200))
|
||||
if _, ok := syscallRules[n]; !ok {
|
||||
syscallRules[n] = []Rule{}
|
||||
syscallRules[n] = MatchAll{}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1019,50 +997,43 @@ func TestRealDeal(t *testing.T) {
|
||||
func TestMerge(t *testing.T) {
|
||||
for _, tst := range []struct {
|
||||
name string
|
||||
main []Rule
|
||||
merge []Rule
|
||||
want []Rule
|
||||
main SyscallRule
|
||||
merge SyscallRule
|
||||
want SyscallRule
|
||||
}{
|
||||
{
|
||||
name: "empty both",
|
||||
main: nil,
|
||||
merge: nil,
|
||||
want: []Rule{{}, {}},
|
||||
name: "AllowAll both",
|
||||
main: MatchAll{},
|
||||
merge: MatchAll{},
|
||||
want: MatchAll{},
|
||||
},
|
||||
{
|
||||
name: "empty main",
|
||||
main: nil,
|
||||
merge: []Rule{{}},
|
||||
want: []Rule{{}, {}},
|
||||
name: "AllowAll and Or",
|
||||
main: MatchAll{},
|
||||
merge: Or{},
|
||||
want: MatchAll{},
|
||||
},
|
||||
{
|
||||
name: "empty merge",
|
||||
main: []Rule{{}},
|
||||
merge: nil,
|
||||
want: []Rule{{}, {}},
|
||||
name: "Or and AllowAll",
|
||||
main: Or{},
|
||||
merge: MatchAll{},
|
||||
want: MatchAll{},
|
||||
},
|
||||
{
|
||||
name: "2 Ors",
|
||||
main: Or{PerArg{EqualTo(0)}},
|
||||
merge: Or{PerArg{EqualTo(1)}},
|
||||
want: Or{PerArg{EqualTo(0)}, PerArg{EqualTo(1)}},
|
||||
},
|
||||
} {
|
||||
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])
|
||||
}
|
||||
wantRules := SyscallRules{1: tst.want}
|
||||
if !reflect.DeepEqual(mainRules, wantRules) {
|
||||
t.Errorf("got rules:\n%v\nwant rules:\n%v\n", mainRules, wantRules)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,69 +30,69 @@ func main() {
|
||||
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_OPENAT: {},
|
||||
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: {},
|
||||
unix.SYS_ACCEPT: seccomp.MatchAll{},
|
||||
unix.SYS_BIND: seccomp.MatchAll{},
|
||||
unix.SYS_BRK: seccomp.MatchAll{},
|
||||
unix.SYS_CLOCK_GETTIME: seccomp.MatchAll{},
|
||||
unix.SYS_CLONE: seccomp.MatchAll{},
|
||||
unix.SYS_CLOSE: seccomp.MatchAll{},
|
||||
unix.SYS_DUP: seccomp.MatchAll{},
|
||||
unix.SYS_DUP3: seccomp.MatchAll{},
|
||||
unix.SYS_EPOLL_CREATE1: seccomp.MatchAll{},
|
||||
unix.SYS_EPOLL_CTL: seccomp.MatchAll{},
|
||||
unix.SYS_EPOLL_PWAIT: seccomp.MatchAll{},
|
||||
unix.SYS_EXIT: seccomp.MatchAll{},
|
||||
unix.SYS_EXIT_GROUP: seccomp.MatchAll{},
|
||||
unix.SYS_FALLOCATE: seccomp.MatchAll{},
|
||||
unix.SYS_FCHMOD: seccomp.MatchAll{},
|
||||
unix.SYS_FCNTL: seccomp.MatchAll{},
|
||||
unix.SYS_FSTAT: seccomp.MatchAll{},
|
||||
unix.SYS_FSYNC: seccomp.MatchAll{},
|
||||
unix.SYS_FTRUNCATE: seccomp.MatchAll{},
|
||||
unix.SYS_FUTEX: seccomp.MatchAll{},
|
||||
unix.SYS_GETDENTS64: seccomp.MatchAll{},
|
||||
unix.SYS_GETPEERNAME: seccomp.MatchAll{},
|
||||
unix.SYS_GETPID: seccomp.MatchAll{},
|
||||
unix.SYS_GETSOCKNAME: seccomp.MatchAll{},
|
||||
unix.SYS_GETSOCKOPT: seccomp.MatchAll{},
|
||||
unix.SYS_GETTID: seccomp.MatchAll{},
|
||||
unix.SYS_GETTIMEOFDAY: seccomp.MatchAll{},
|
||||
unix.SYS_LISTEN: seccomp.MatchAll{},
|
||||
unix.SYS_LSEEK: seccomp.MatchAll{},
|
||||
unix.SYS_MADVISE: seccomp.MatchAll{},
|
||||
unix.SYS_MINCORE: seccomp.MatchAll{},
|
||||
unix.SYS_MMAP: seccomp.MatchAll{},
|
||||
unix.SYS_MPROTECT: seccomp.MatchAll{},
|
||||
unix.SYS_MUNLOCK: seccomp.MatchAll{},
|
||||
unix.SYS_MUNMAP: seccomp.MatchAll{},
|
||||
unix.SYS_NANOSLEEP: seccomp.MatchAll{},
|
||||
unix.SYS_OPENAT: seccomp.MatchAll{},
|
||||
unix.SYS_PPOLL: seccomp.MatchAll{},
|
||||
unix.SYS_PREAD64: seccomp.MatchAll{},
|
||||
unix.SYS_PSELECT6: seccomp.MatchAll{},
|
||||
unix.SYS_PWRITE64: seccomp.MatchAll{},
|
||||
unix.SYS_READ: seccomp.MatchAll{},
|
||||
unix.SYS_READLINKAT: seccomp.MatchAll{},
|
||||
unix.SYS_READV: seccomp.MatchAll{},
|
||||
unix.SYS_RECVMSG: seccomp.MatchAll{},
|
||||
unix.SYS_RENAMEAT: seccomp.MatchAll{},
|
||||
unix.SYS_RESTART_SYSCALL: seccomp.MatchAll{},
|
||||
unix.SYS_RT_SIGACTION: seccomp.MatchAll{},
|
||||
unix.SYS_RT_SIGPROCMASK: seccomp.MatchAll{},
|
||||
unix.SYS_RT_SIGRETURN: seccomp.MatchAll{},
|
||||
unix.SYS_SCHED_YIELD: seccomp.MatchAll{},
|
||||
unix.SYS_SENDMSG: seccomp.MatchAll{},
|
||||
unix.SYS_SETITIMER: seccomp.MatchAll{},
|
||||
unix.SYS_SET_ROBUST_LIST: seccomp.MatchAll{},
|
||||
unix.SYS_SETSOCKOPT: seccomp.MatchAll{},
|
||||
unix.SYS_SHUTDOWN: seccomp.MatchAll{},
|
||||
unix.SYS_SIGALTSTACK: seccomp.MatchAll{},
|
||||
unix.SYS_SOCKET: seccomp.MatchAll{},
|
||||
unix.SYS_SYNC_FILE_RANGE: seccomp.MatchAll{},
|
||||
unix.SYS_TGKILL: seccomp.MatchAll{},
|
||||
unix.SYS_UTIMENSAT: seccomp.MatchAll{},
|
||||
unix.SYS_WRITE: seccomp.MatchAll{},
|
||||
unix.SYS_WRITEV: seccomp.MatchAll{},
|
||||
}
|
||||
|
||||
arch_syscalls(syscalls)
|
||||
@@ -102,10 +102,8 @@ func main() {
|
||||
|
||||
die := *dieFlag
|
||||
if !die {
|
||||
syscalls[syscall] = []seccomp.Rule{
|
||||
{
|
||||
seccomp.EqualTo(0),
|
||||
},
|
||||
syscalls[syscall] = seccomp.PerArg{
|
||||
seccomp.EqualTo(0),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ import (
|
||||
)
|
||||
|
||||
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{}
|
||||
syscalls[unix.SYS_ARCH_PRCTL] = seccomp.MatchAll{}
|
||||
syscalls[unix.SYS_EPOLL_WAIT] = seccomp.MatchAll{}
|
||||
syscalls[unix.SYS_NEWFSTATAT] = seccomp.MatchAll{}
|
||||
syscalls[unix.SYS_OPEN] = seccomp.MatchAll{}
|
||||
}
|
||||
|
||||
@@ -26,5 +26,5 @@ import (
|
||||
)
|
||||
|
||||
func arch_syscalls(syscalls seccomp.SyscallRules) {
|
||||
syscalls[unix.SYS_FSTATAT] = []seccomp.Rule{}
|
||||
syscalls[unix.SYS_FSTATAT] = seccomp.MatchAll{}
|
||||
}
|
||||
|
||||
@@ -25,92 +25,88 @@ import (
|
||||
func Filters() seccomp.SyscallRules {
|
||||
nonNegativeFD := seccomp.NonNegativeFDCheck()
|
||||
return seccomp.SyscallRules{
|
||||
unix.SYS_OPENAT: []seccomp.Rule{
|
||||
{
|
||||
// All paths that we openat() are absolute, so we pass a dirfd
|
||||
// of -1 (which is invalid for relative paths, but ignored for
|
||||
// absolute paths) to hedge against bugs involving AT_FDCWD or
|
||||
// real dirfds.
|
||||
seccomp.EqualTo(^uintptr(0)),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.MaskedEqual(unix.O_CREAT|unix.O_NOFOLLOW, unix.O_NOFOLLOW),
|
||||
seccomp.AnyValue{},
|
||||
},
|
||||
unix.SYS_OPENAT: seccomp.PerArg{
|
||||
// All paths that we openat() are absolute, so we pass a dirfd
|
||||
// of -1 (which is invalid for relative paths, but ignored for
|
||||
// absolute paths) to hedge against bugs involving AT_FDCWD or
|
||||
// real dirfds.
|
||||
seccomp.EqualTo(^uintptr(0)),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.MaskedEqual(unix.O_CREAT|unix.O_NOFOLLOW, unix.O_NOFOLLOW),
|
||||
seccomp.AnyValue{},
|
||||
},
|
||||
unix.SYS_GETDENTS64: {},
|
||||
unix.SYS_IOCTL: []seccomp.Rule{
|
||||
{
|
||||
unix.SYS_GETDENTS64: seccomp.MatchAll{},
|
||||
unix.SYS_IOCTL: seccomp.Or{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_RESET),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_SET_EVENTFD),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_CLEAR_EVENTFD),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_NUMBER_PAGE_TABLES),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_PAGE_TABLE_SIZE),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_SIMPLE_PAGE_TABLE_SIZE),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_PARTITION_PAGE_TABLE),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_MAP_BUFFER),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_UNMAP_BUFFER),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_CLEAR_INTERRUPT_COUNTS),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_REGISTER_INTERRUPT),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_UNREGISTER_INTERRUPT),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_MAP_DMA_BUF),
|
||||
},
|
||||
},
|
||||
unix.SYS_EVENTFD2: []seccomp.Rule{
|
||||
{
|
||||
unix.SYS_EVENTFD2: seccomp.Or{
|
||||
seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(linux.EFD_NONBLOCK),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(linux.EFD_NONBLOCK | linux.EFD_SEMAPHORE),
|
||||
},
|
||||
},
|
||||
unix.SYS_MREMAP: []seccomp.Rule{
|
||||
{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(0), /* old_size */
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(linux.MREMAP_MAYMOVE | linux.MREMAP_FIXED),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(0),
|
||||
},
|
||||
unix.SYS_MREMAP: seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(0), /* old_size */
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(linux.MREMAP_MAYMOVE | linux.MREMAP_FIXED),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(0),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,165 +26,161 @@ func Filters() seccomp.SyscallRules {
|
||||
nonNegativeFD := seccomp.NonNegativeFDCheck()
|
||||
notIocSizeMask := ^(((uintptr(1) << linux.IOC_SIZEBITS) - 1) << linux.IOC_SIZESHIFT) // for ioctls taking arbitrary size
|
||||
return seccomp.SyscallRules{
|
||||
unix.SYS_OPENAT: []seccomp.Rule{
|
||||
{
|
||||
// All paths that we openat() are absolute, so we pass a dirfd
|
||||
// of -1 (which is invalid for relative paths, but ignored for
|
||||
// absolute paths) to hedge against bugs involving AT_FDCWD or
|
||||
// real dirfds.
|
||||
seccomp.EqualTo(^uintptr(0)),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.MaskedEqual(unix.O_NOFOLLOW|unix.O_CREAT, unix.O_NOFOLLOW),
|
||||
seccomp.AnyValue{},
|
||||
},
|
||||
unix.SYS_OPENAT: seccomp.PerArg{
|
||||
// All paths that we openat() are absolute, so we pass a dirfd
|
||||
// of -1 (which is invalid for relative paths, but ignored for
|
||||
// absolute paths) to hedge against bugs involving AT_FDCWD or
|
||||
// real dirfds.
|
||||
seccomp.EqualTo(^uintptr(0)),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.MaskedEqual(unix.O_NOFOLLOW|unix.O_CREAT, unix.O_NOFOLLOW),
|
||||
seccomp.AnyValue{},
|
||||
},
|
||||
unix.SYS_IOCTL: []seccomp.Rule{
|
||||
{
|
||||
unix.SYS_IOCTL: seccomp.Or{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.MaskedEqual(notIocSizeMask, frontendIoctlCmd(nvgpu.NV_ESC_CARD_INFO, 0)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_CHECK_VERSION_STR, nvgpu.SizeofRMAPIVersion)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_REGISTER_FD, nvgpu.SizeofIoctlRegisterFD)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_ALLOC_OS_EVENT, nvgpu.SizeofIoctlAllocOSEvent)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_FREE_OS_EVENT, nvgpu.SizeofIoctlFreeOSEvent)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_SYS_PARAMS, nvgpu.SizeofIoctlSysParams)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_ALLOC_MEMORY, nvgpu.SizeofIoctlNVOS02ParametersWithFD)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_FREE, nvgpu.SizeofNVOS00Parameters)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_CONTROL, nvgpu.SizeofNVOS54Parameters)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_ALLOC, nvgpu.SizeofNVOS21Parameters)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_ALLOC, nvgpu.SizeofNVOS64Parameters)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_DUP_OBJECT, nvgpu.SizeofNVOS55Parameters)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_SHARE, nvgpu.SizeofNVOS57Parameters)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_VID_HEAP_CONTROL, nvgpu.SizeofNVOS32Parameters)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_MAP_MEMORY, nvgpu.SizeofIoctlNVOS33ParametersWithFD)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_UNMAP_MEMORY, nvgpu.SizeofNVOS34Parameters)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_UPDATE_DEVICE_MAPPING_INFO, nvgpu.SizeofNVOS56Parameters)),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_INITIALIZE),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_DEINITIALIZE),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_CREATE_RANGE_GROUP),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_DESTROY_RANGE_GROUP),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_REGISTER_GPU_VASPACE),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_UNREGISTER_GPU_VASPACE),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_REGISTER_CHANNEL),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_UNREGISTER_CHANNEL),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_MAP_EXTERNAL_ALLOCATION),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_FREE),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_REGISTER_GPU),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_UNREGISTER_GPU),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_PAGEABLE_MEM_ACCESS),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_MAP_DYNAMIC_PARALLELISM_REGION),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_ALLOC_SEMAPHORE_POOL),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_VALIDATE_VA_RANGE),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(nvgpu.UVM_CREATE_EXTERNAL_RANGE),
|
||||
},
|
||||
},
|
||||
unix.SYS_MREMAP: []seccomp.Rule{
|
||||
{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(0), /* old_size */
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(linux.MREMAP_MAYMOVE | linux.MREMAP_FIXED),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(0),
|
||||
},
|
||||
unix.SYS_MREMAP: seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(0), /* old_size */
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(linux.MREMAP_MAYMOVE | linux.MREMAP_FIXED),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(0),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,34 +25,32 @@ import (
|
||||
func (k *KVM) SyscallFilters() seccomp.SyscallRules {
|
||||
r := k.archSyscallFilters()
|
||||
r.Merge(seccomp.SyscallRules{
|
||||
unix.SYS_IOCTL: []seccomp.Rule{
|
||||
{
|
||||
unix.SYS_IOCTL: seccomp.Or{
|
||||
seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(KVM_RUN),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(KVM_SET_USER_MEMORY_REGION),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(KVM_GET_REGS),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(KVM_SET_REGS),
|
||||
},
|
||||
},
|
||||
unix.SYS_MEMBARRIER: []seccomp.Rule{
|
||||
{
|
||||
seccomp.EqualTo(linux.MEMBARRIER_CMD_PRIVATE_EXPEDITED),
|
||||
seccomp.EqualTo(0),
|
||||
},
|
||||
unix.SYS_MEMBARRIER: seccomp.PerArg{
|
||||
seccomp.EqualTo(linux.MEMBARRIER_CMD_PRIVATE_EXPEDITED),
|
||||
seccomp.EqualTo(0),
|
||||
},
|
||||
unix.SYS_MMAP: {},
|
||||
unix.SYS_RT_SIGSUSPEND: {},
|
||||
unix.SYS_RT_SIGTIMEDWAIT: {},
|
||||
_SYS_KVM_RETURN_TO_HOST: {},
|
||||
unix.SYS_MMAP: seccomp.MatchAll{},
|
||||
unix.SYS_RT_SIGSUSPEND: seccomp.MatchAll{},
|
||||
unix.SYS_RT_SIGTIMEDWAIT: seccomp.MatchAll{},
|
||||
_SYS_KVM_RETURN_TO_HOST: seccomp.MatchAll{},
|
||||
})
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -25,24 +25,24 @@ import (
|
||||
// KVM platform.
|
||||
func (k *KVM) archSyscallFilters() seccomp.SyscallRules {
|
||||
return seccomp.SyscallRules{
|
||||
unix.SYS_ARCH_PRCTL: {
|
||||
{
|
||||
unix.SYS_ARCH_PRCTL: seccomp.Or{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(linux.ARCH_GET_FS),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(linux.ARCH_GET_GS),
|
||||
},
|
||||
},
|
||||
unix.SYS_IOCTL: []seccomp.Rule{
|
||||
{
|
||||
unix.SYS_IOCTL: seccomp.Or{
|
||||
seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(KVM_INTERRUPT),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(KVM_NMI),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(KVM_GET_REGS),
|
||||
},
|
||||
|
||||
@@ -27,11 +27,9 @@ import (
|
||||
// KVM platform.
|
||||
func (*KVM) archSyscallFilters() seccomp.SyscallRules {
|
||||
return seccomp.SyscallRules{
|
||||
unix.SYS_IOCTL: {
|
||||
{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(KVM_SET_VCPU_EVENTS),
|
||||
},
|
||||
unix.SYS_IOCTL: seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(KVM_SET_VCPU_EVENTS),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -776,24 +776,21 @@ func seccompMmapRules(m *machine) {
|
||||
if err := sighandling.ReplaceSignalHandler(unix.SIGSYS, addrOfSigsysHandler(), &savedSigsysHandler); err != nil {
|
||||
panic(fmt.Sprintf("Unable to set handler for signal %d: %v", bluepillSignal, err))
|
||||
}
|
||||
rules := []seccomp.RuleSet{}
|
||||
rules = append(rules, []seccomp.RuleSet{
|
||||
rules := []seccomp.RuleSet{
|
||||
// Trap mmap system calls and handle them in sigsysGoHandler
|
||||
{
|
||||
Rules: seccomp.SyscallRules{
|
||||
unix.SYS_MMAP: {
|
||||
{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.AnyValue{},
|
||||
seccomp.MaskedEqual(unix.PROT_EXEC, 0),
|
||||
/* MAP_DENYWRITE is ignored and used only for filtering. */
|
||||
seccomp.MaskedEqual(unix.MAP_DENYWRITE, 0),
|
||||
},
|
||||
unix.SYS_MMAP: seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.AnyValue{},
|
||||
seccomp.MaskedEqual(unix.PROT_EXEC, 0),
|
||||
/* MAP_DENYWRITE is ignored and used only for filtering. */
|
||||
seccomp.MaskedEqual(unix.MAP_DENYWRITE, 0),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_TRAP,
|
||||
},
|
||||
}...)
|
||||
}
|
||||
instrs, err := seccomp.BuildProgram(rules, linux.SECCOMP_RET_ALLOW, linux.SECCOMP_RET_ALLOW)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to build rules: %v", err))
|
||||
|
||||
@@ -22,8 +22,8 @@ import (
|
||||
// SyscallFilters returns syscalls made exclusively by the ptrace platform.
|
||||
func (*PTrace) SyscallFilters() seccomp.SyscallRules {
|
||||
return seccomp.SyscallRules{
|
||||
unix.SYS_PTRACE: {},
|
||||
unix.SYS_TGKILL: {},
|
||||
unix.SYS_WAIT4: {},
|
||||
unix.SYS_PTRACE: seccomp.MatchAll{},
|
||||
unix.SYS_TGKILL: seccomp.MatchAll{},
|
||||
unix.SYS_WAIT4: seccomp.MatchAll{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,9 +184,9 @@ func appendArchSeccompRules(rules []seccomp.RuleSet, defaultAction linux.BPFActi
|
||||
// Rules for trapping vsyscall access.
|
||||
seccomp.RuleSet{
|
||||
Rules: seccomp.SyscallRules{
|
||||
unix.SYS_GETTIMEOFDAY: {},
|
||||
unix.SYS_TIME: {},
|
||||
unix.SYS_GETCPU: {}, // SYS_GETCPU was not defined in package syscall on amd64.
|
||||
unix.SYS_GETTIMEOFDAY: seccomp.MatchAll{},
|
||||
unix.SYS_TIME: seccomp.MatchAll{},
|
||||
unix.SYS_GETCPU: seccomp.MatchAll{}, // SYS_GETCPU was not defined in package syscall on amd64.
|
||||
},
|
||||
Action: linux.SECCOMP_RET_TRAP,
|
||||
Vsyscall: true,
|
||||
@@ -195,8 +195,9 @@ func appendArchSeccompRules(rules []seccomp.RuleSet, defaultAction linux.BPFActi
|
||||
rules = append(rules,
|
||||
seccomp.RuleSet{
|
||||
Rules: seccomp.SyscallRules{
|
||||
unix.SYS_ARCH_PRCTL: []seccomp.Rule{
|
||||
{seccomp.EqualTo(linux.ARCH_SET_CPUID), seccomp.EqualTo(0)},
|
||||
unix.SYS_ARCH_PRCTL: seccomp.PerArg{
|
||||
seccomp.EqualTo(linux.ARCH_SET_CPUID),
|
||||
seccomp.EqualTo(0),
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
|
||||
@@ -113,7 +113,7 @@ func dumpRegs(regs *arch.Registers) string {
|
||||
}
|
||||
|
||||
// adjustInitregsRip adjust the current register RIP value to
|
||||
// be just before the system call instruction excution
|
||||
// be just before the system call instruction execution
|
||||
func (t *thread) adjustInitRegsRip() {
|
||||
t.initRegs.Pc -= initRegsRipAdjustment
|
||||
}
|
||||
|
||||
@@ -80,38 +80,35 @@ func attachedThread(flags uintptr, defaultAction linux.BPFAction) (*thread, erro
|
||||
if defaultAction != linux.SECCOMP_RET_ALLOW {
|
||||
rules = append(rules, seccomp.RuleSet{
|
||||
Rules: seccomp.SyscallRules{
|
||||
unix.SYS_CLONE: []seccomp.Rule{
|
||||
unix.SYS_CLONE: seccomp.Or{
|
||||
// Allow creation of new subprocesses (used by the master).
|
||||
{seccomp.EqualTo(unix.CLONE_FILES | unix.SIGKILL)},
|
||||
seccomp.PerArg{seccomp.EqualTo(unix.CLONE_FILES | unix.SIGKILL)},
|
||||
// Allow creation of new threads within a single address space (used by addresss spaces).
|
||||
{seccomp.EqualTo(
|
||||
unix.CLONE_FILES |
|
||||
unix.CLONE_FS |
|
||||
unix.CLONE_SIGHAND |
|
||||
unix.CLONE_THREAD |
|
||||
unix.CLONE_PTRACE |
|
||||
unix.CLONE_VM)},
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(
|
||||
unix.CLONE_FILES |
|
||||
unix.CLONE_FS |
|
||||
unix.CLONE_SIGHAND |
|
||||
unix.CLONE_THREAD |
|
||||
unix.CLONE_PTRACE |
|
||||
unix.CLONE_VM)},
|
||||
},
|
||||
|
||||
// For the initial process creation.
|
||||
unix.SYS_WAIT4: {},
|
||||
unix.SYS_EXIT: {},
|
||||
unix.SYS_WAIT4: seccomp.MatchAll{},
|
||||
unix.SYS_EXIT: seccomp.MatchAll{},
|
||||
|
||||
// For the stub prctl dance (all).
|
||||
unix.SYS_PRCTL: []seccomp.Rule{
|
||||
{seccomp.EqualTo(unix.PR_SET_PDEATHSIG), seccomp.EqualTo(unix.SIGKILL)},
|
||||
},
|
||||
unix.SYS_GETPPID: {},
|
||||
unix.SYS_PRCTL: seccomp.PerArg{seccomp.EqualTo(unix.PR_SET_PDEATHSIG), seccomp.EqualTo(unix.SIGKILL)},
|
||||
unix.SYS_GETPPID: seccomp.MatchAll{},
|
||||
|
||||
// For the stub to stop itself (all).
|
||||
unix.SYS_GETPID: {},
|
||||
unix.SYS_KILL: []seccomp.Rule{
|
||||
{seccomp.AnyValue{}, seccomp.EqualTo(unix.SIGSTOP)},
|
||||
},
|
||||
unix.SYS_GETPID: seccomp.MatchAll{},
|
||||
unix.SYS_KILL: seccomp.PerArg{seccomp.AnyValue{}, seccomp.EqualTo(unix.SIGSTOP)},
|
||||
|
||||
// Injected to support the address space operations.
|
||||
unix.SYS_MMAP: {},
|
||||
unix.SYS_MUNMAP: {},
|
||||
unix.SYS_MMAP: seccomp.MatchAll{},
|
||||
unix.SYS_MUNMAP: seccomp.MatchAll{},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
})
|
||||
|
||||
@@ -23,61 +23,59 @@ import (
|
||||
// SyscallFilters returns syscalls made exclusively by the systrap platform.
|
||||
func (p *Systrap) SyscallFilters() seccomp.SyscallRules {
|
||||
r := seccomp.SyscallRules{
|
||||
unix.SYS_PTRACE: {
|
||||
{
|
||||
unix.SYS_PTRACE: seccomp.Or{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(unix.PTRACE_ATTACH),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(unix.PTRACE_CONT),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(0),
|
||||
seccomp.EqualTo(0),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(unix.PTRACE_GETEVENTMSG),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(unix.PTRACE_GETREGSET),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(linux.NT_PRSTATUS),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(unix.PTRACE_GETSIGINFO),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(unix.PTRACE_SETOPTIONS),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(0),
|
||||
seccomp.EqualTo(unix.PTRACE_O_TRACESYSGOOD | unix.PTRACE_O_TRACEEXIT | unix.PTRACE_O_EXITKILL),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(unix.PTRACE_SETREGSET),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(linux.NT_PRSTATUS),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(linux.PTRACE_SETSIGMASK),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(8),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(unix.PTRACE_SYSEMU),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(0),
|
||||
seccomp.EqualTo(0),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(unix.PTRACE_DETACH),
|
||||
},
|
||||
},
|
||||
unix.SYS_TGKILL: {},
|
||||
unix.SYS_WAIT4: {},
|
||||
unix.SYS_SETPRIORITY: {
|
||||
{
|
||||
seccomp.EqualTo(unix.PRIO_PROCESS),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(sysmsgThreadPriority),
|
||||
},
|
||||
unix.SYS_TGKILL: seccomp.MatchAll{},
|
||||
unix.SYS_WAIT4: seccomp.MatchAll{},
|
||||
unix.SYS_SETPRIORITY: seccomp.PerArg{
|
||||
seccomp.EqualTo(unix.PRIO_PROCESS),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(sysmsgThreadPriority),
|
||||
},
|
||||
}
|
||||
r.Merge(p.archSyscallFilters())
|
||||
|
||||
@@ -26,13 +26,13 @@ import (
|
||||
// SyscallFilters returns syscalls made exclusively by the systrap platform.
|
||||
func (*Systrap) archSyscallFilters() seccomp.SyscallRules {
|
||||
return seccomp.SyscallRules{
|
||||
unix.SYS_PTRACE: {
|
||||
{
|
||||
unix.SYS_PTRACE: seccomp.Or{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(unix.PTRACE_GETREGSET),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(linux.NT_ARM_TLS),
|
||||
},
|
||||
{
|
||||
seccomp.PerArg{
|
||||
seccomp.EqualTo(unix.PTRACE_SETREGSET),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(linux.NT_ARM_TLS),
|
||||
|
||||
@@ -185,19 +185,19 @@ func appendArchSeccompRules(rules []seccomp.RuleSet) []seccomp.RuleSet {
|
||||
// Rules for trapping vsyscall access.
|
||||
{
|
||||
Rules: seccomp.SyscallRules{
|
||||
unix.SYS_GETTIMEOFDAY: {},
|
||||
unix.SYS_TIME: {},
|
||||
unix.SYS_GETCPU: {}, // SYS_GETCPU was not defined in package syscall on amd64.
|
||||
unix.SYS_GETTIMEOFDAY: seccomp.MatchAll{},
|
||||
unix.SYS_TIME: seccomp.MatchAll{},
|
||||
unix.SYS_GETCPU: seccomp.MatchAll{}, // SYS_GETCPU was not defined in package syscall on amd64.
|
||||
},
|
||||
Action: linux.SECCOMP_RET_TRAP,
|
||||
Vsyscall: true,
|
||||
},
|
||||
{
|
||||
Rules: seccomp.SyscallRules{
|
||||
unix.SYS_ARCH_PRCTL: []seccomp.Rule{
|
||||
{seccomp.EqualTo(linux.ARCH_SET_CPUID), seccomp.EqualTo(0)},
|
||||
{seccomp.EqualTo(linux.ARCH_SET_FS)},
|
||||
{seccomp.EqualTo(linux.ARCH_GET_FS)},
|
||||
unix.SYS_ARCH_PRCTL: seccomp.Or{
|
||||
seccomp.PerArg{seccomp.EqualTo(linux.ARCH_SET_CPUID), seccomp.EqualTo(0)},
|
||||
seccomp.PerArg{seccomp.EqualTo(linux.ARCH_SET_FS)},
|
||||
seccomp.PerArg{seccomp.EqualTo(linux.ARCH_GET_FS)},
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
|
||||
@@ -55,17 +55,17 @@ func attachedThread(flags uintptr, defaultAction linux.BPFAction) (*thread, erro
|
||||
if defaultAction != linux.SECCOMP_RET_ALLOW {
|
||||
ruleSet := seccomp.RuleSet{
|
||||
Rules: seccomp.SyscallRules{
|
||||
unix.SYS_CLONE: []seccomp.Rule{
|
||||
unix.SYS_CLONE: seccomp.Or{
|
||||
// Allow creation of new subprocesses (used by the master).
|
||||
{seccomp.EqualTo(unix.CLONE_FILES | unix.SIGKILL)},
|
||||
seccomp.PerArg{seccomp.EqualTo(unix.CLONE_FILES | unix.SIGKILL)},
|
||||
// Allow creation of new sysmsg thread.
|
||||
{seccomp.EqualTo(
|
||||
seccomp.PerArg{seccomp.EqualTo(
|
||||
unix.CLONE_FILES |
|
||||
unix.CLONE_FS |
|
||||
unix.CLONE_VM |
|
||||
unix.CLONE_PTRACE)},
|
||||
// Allow creation of new threads within a single address space (used by addresss spaces).
|
||||
{seccomp.EqualTo(
|
||||
seccomp.PerArg{seccomp.EqualTo(
|
||||
unix.CLONE_FILES |
|
||||
unix.CLONE_FS |
|
||||
unix.CLONE_SIGHAND |
|
||||
@@ -75,50 +75,54 @@ func attachedThread(flags uintptr, defaultAction linux.BPFAction) (*thread, erro
|
||||
},
|
||||
|
||||
// For the initial process creation.
|
||||
unix.SYS_WAIT4: {},
|
||||
unix.SYS_EXIT: {},
|
||||
unix.SYS_WAIT4: seccomp.MatchAll{},
|
||||
unix.SYS_EXIT: seccomp.MatchAll{},
|
||||
|
||||
// For the stub prctl dance (all).
|
||||
unix.SYS_PRCTL: []seccomp.Rule{
|
||||
{seccomp.EqualTo(unix.PR_SET_PDEATHSIG), seccomp.EqualTo(unix.SIGKILL)},
|
||||
{seccomp.EqualTo(linux.PR_SET_NO_NEW_PRIVS), seccomp.EqualTo(1)},
|
||||
unix.SYS_PRCTL: seccomp.Or{
|
||||
seccomp.PerArg{seccomp.EqualTo(unix.PR_SET_PDEATHSIG), seccomp.EqualTo(unix.SIGKILL)},
|
||||
seccomp.PerArg{seccomp.EqualTo(linux.PR_SET_NO_NEW_PRIVS), seccomp.EqualTo(1)},
|
||||
},
|
||||
unix.SYS_GETPPID: {},
|
||||
unix.SYS_GETPPID: seccomp.MatchAll{},
|
||||
|
||||
// For the stub to stop itself (all).
|
||||
unix.SYS_GETPID: {},
|
||||
unix.SYS_KILL: []seccomp.Rule{
|
||||
{seccomp.AnyValue{}, seccomp.EqualTo(unix.SIGSTOP)},
|
||||
unix.SYS_GETPID: seccomp.MatchAll{},
|
||||
unix.SYS_KILL: seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(unix.SIGSTOP),
|
||||
},
|
||||
|
||||
// Injected to support the address space operations.
|
||||
unix.SYS_MMAP: {},
|
||||
unix.SYS_MUNMAP: {},
|
||||
unix.SYS_MMAP: seccomp.MatchAll{},
|
||||
unix.SYS_MUNMAP: seccomp.MatchAll{},
|
||||
|
||||
// For sysmsg threads. Look at sysmsg/sighandler.c for more details.
|
||||
unix.SYS_RT_SIGRETURN: {},
|
||||
unix.SYS_SCHED_YIELD: {},
|
||||
unix.SYS_FUTEX: {
|
||||
seccomp.Rule{
|
||||
unix.SYS_RT_SIGRETURN: seccomp.MatchAll{},
|
||||
unix.SYS_SCHED_YIELD: seccomp.MatchAll{},
|
||||
unix.SYS_FUTEX: seccomp.Or{
|
||||
seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(linux.FUTEX_WAIT),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.AnyValue{},
|
||||
},
|
||||
seccomp.Rule{
|
||||
seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(linux.FUTEX_WAKE),
|
||||
seccomp.AnyValue{},
|
||||
seccomp.AnyValue{},
|
||||
},
|
||||
},
|
||||
unix.SYS_SIGALTSTACK: {},
|
||||
unix.SYS_TKILL: {
|
||||
{seccomp.AnyValue{}, seccomp.EqualTo(unix.SIGSTOP)},
|
||||
unix.SYS_SIGALTSTACK: seccomp.MatchAll{},
|
||||
unix.SYS_TKILL: seccomp.PerArg{
|
||||
seccomp.AnyValue{},
|
||||
seccomp.EqualTo(unix.SIGSTOP),
|
||||
},
|
||||
unix.SYS_GETTID: {},
|
||||
seccomp.SYS_SECCOMP: {
|
||||
{seccomp.EqualTo(linux.SECCOMP_SET_MODE_FILTER), seccomp.EqualTo(0), seccomp.AnyValue{}},
|
||||
unix.SYS_GETTID: seccomp.MatchAll{},
|
||||
seccomp.SYS_SECCOMP: seccomp.PerArg{
|
||||
seccomp.EqualTo(linux.SECCOMP_SET_MODE_FILTER),
|
||||
seccomp.EqualTo(0),
|
||||
seccomp.AnyValue{},
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user