diff options
Diffstat (limited to 'vendor/github.com/opencontainers/runtime-tools/generate/seccomp')
7 files changed, 1044 insertions, 0 deletions
diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go new file mode 100644 index 000000000..eade5718e --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/consts.go @@ -0,0 +1,12 @@ +package seccomp + +const ( + seccompOverwrite = "overwrite" + seccompAppend = "append" + nothing = "nothing" + kill = "kill" + trap = "trap" + trace = "trace" + allow = "allow" + errno = "errno" +) diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_action.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_action.go new file mode 100644 index 000000000..25daf0752 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_action.go @@ -0,0 +1,135 @@ +package seccomp + +import ( + "fmt" + "strconv" + "strings" + + rspec "github.com/opencontainers/runtime-spec/specs-go" +) + +// SyscallOpts contain options for parsing syscall rules +type SyscallOpts struct { + Action string + Syscall string + Index string + Value string + ValueTwo string + Operator string +} + +// ParseSyscallFlag takes a SyscallOpts struct and the seccomp configuration +// and sets the new syscall rule accordingly +func ParseSyscallFlag(args SyscallOpts, config *rspec.LinuxSeccomp) error { + var arguments []string + if args.Index != "" && args.Value != "" && args.ValueTwo != "" && args.Operator != "" { + arguments = []string{args.Action, args.Syscall, args.Index, args.Value, + args.ValueTwo, args.Operator} + } else { + arguments = []string{args.Action, args.Syscall} + } + + action, _ := parseAction(arguments[0]) + if action == config.DefaultAction && args.argsAreEmpty() { + // default already set, no need to make changes + return nil + } + + var newSyscall rspec.LinuxSyscall + numOfArgs := len(arguments) + if numOfArgs == 6 || numOfArgs == 2 { + argStruct, err := parseArguments(arguments[1:]) + if err != nil { + return err + } + newSyscall = newSyscallStruct(arguments[1], action, argStruct) + } else { + return fmt.Errorf("incorrect number of arguments to ParseSyscall: %d", numOfArgs) + } + + descison, err := decideCourseOfAction(&newSyscall, config.Syscalls) + if err != nil { + return err + } + delimDescison := strings.Split(descison, ":") + + if delimDescison[0] == seccompAppend { + config.Syscalls = append(config.Syscalls, newSyscall) + } + + if delimDescison[0] == seccompOverwrite { + indexForOverwrite, err := strconv.ParseInt(delimDescison[1], 10, 32) + if err != nil { + return err + } + config.Syscalls[indexForOverwrite] = newSyscall + } + + return nil +} + +var actions = map[string]rspec.LinuxSeccompAction{ + "allow": rspec.ActAllow, + "errno": rspec.ActErrno, + "kill": rspec.ActKill, + "trace": rspec.ActTrace, + "trap": rspec.ActTrap, +} + +// Take passed action, return the SCMP_ACT_<ACTION> version of it +func parseAction(action string) (rspec.LinuxSeccompAction, error) { + a, ok := actions[action] + if !ok { + return "", fmt.Errorf("unrecognized action: %s", action) + } + return a, nil +} + +// ParseDefaultAction sets the default action of the seccomp configuration +// and then removes any rules that were already specified with this action +func ParseDefaultAction(action string, config *rspec.LinuxSeccomp) error { + if action == "" { + return nil + } + + defaultAction, err := parseAction(action) + if err != nil { + return err + } + config.DefaultAction = defaultAction + err = RemoveAllMatchingRules(config, defaultAction) + if err != nil { + return err + } + return nil +} + +// ParseDefaultActionForce simply sets the default action of the seccomp configuration +func ParseDefaultActionForce(action string, config *rspec.LinuxSeccomp) error { + if action == "" { + return nil + } + + defaultAction, err := parseAction(action) + if err != nil { + return err + } + config.DefaultAction = defaultAction + return nil +} + +func newSyscallStruct(name string, action rspec.LinuxSeccompAction, args []rspec.LinuxSeccompArg) rspec.LinuxSyscall { + syscallStruct := rspec.LinuxSyscall{ + Names: []string{name}, + Action: action, + Args: args, + } + return syscallStruct +} + +func (s SyscallOpts) argsAreEmpty() bool { + return (s.Index == "" && + s.Value == "" && + s.ValueTwo == "" && + s.Operator == "") +} diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_architecture.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_architecture.go new file mode 100644 index 000000000..9b2bdfd2f --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_architecture.go @@ -0,0 +1,55 @@ +package seccomp + +import ( + "fmt" + + rspec "github.com/opencontainers/runtime-spec/specs-go" +) + +// ParseArchitectureFlag takes the raw string passed with the --arch flag, parses it +// and updates the Seccomp config accordingly +func ParseArchitectureFlag(architectureArg string, config *rspec.LinuxSeccomp) error { + correctedArch, err := parseArch(architectureArg) + if err != nil { + return err + } + + shouldAppend := true + for _, alreadySpecified := range config.Architectures { + if correctedArch == alreadySpecified { + shouldAppend = false + } + } + if shouldAppend { + config.Architectures = append(config.Architectures, correctedArch) + } + return nil +} + +func parseArch(arch string) (rspec.Arch, error) { + arches := map[string]rspec.Arch{ + "x86": rspec.ArchX86, + "amd64": rspec.ArchX86_64, + "x32": rspec.ArchX32, + "arm": rspec.ArchARM, + "arm64": rspec.ArchAARCH64, + "mips": rspec.ArchMIPS, + "mips64": rspec.ArchMIPS64, + "mips64n32": rspec.ArchMIPS64N32, + "mipsel": rspec.ArchMIPSEL, + "mipsel64": rspec.ArchMIPSEL64, + "mipsel64n32": rspec.ArchMIPSEL64N32, + "parisc": rspec.ArchPARISC, + "parisc64": rspec.ArchPARISC64, + "ppc": rspec.ArchPPC, + "ppc64": rspec.ArchPPC64, + "ppc64le": rspec.ArchPPC64LE, + "s390": rspec.ArchS390, + "s390x": rspec.ArchS390X, + } + a, ok := arches[arch] + if !ok { + return "", fmt.Errorf("unrecognized architecture: %s", arch) + } + return a, nil +} diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_arguments.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_arguments.go new file mode 100644 index 000000000..2b4c394e6 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_arguments.go @@ -0,0 +1,73 @@ +package seccomp + +import ( + "fmt" + "strconv" + + rspec "github.com/opencontainers/runtime-spec/specs-go" +) + +// parseArguments takes a list of arguments (delimArgs). It parses and fills out +// the argument information and returns a slice of arg structs +func parseArguments(delimArgs []string) ([]rspec.LinuxSeccompArg, error) { + nilArgSlice := []rspec.LinuxSeccompArg{} + numberOfArgs := len(delimArgs) + + // No parameters passed with syscall + if numberOfArgs == 1 { + return nilArgSlice, nil + } + + // Correct number of parameters passed with syscall + if numberOfArgs == 5 { + syscallIndex, err := strconv.ParseUint(delimArgs[1], 10, 0) + if err != nil { + return nilArgSlice, err + } + + syscallValue, err := strconv.ParseUint(delimArgs[2], 10, 64) + if err != nil { + return nilArgSlice, err + } + + syscallValueTwo, err := strconv.ParseUint(delimArgs[3], 10, 64) + if err != nil { + return nilArgSlice, err + } + + syscallOp, err := parseOperator(delimArgs[4]) + if err != nil { + return nilArgSlice, err + } + + argStruct := rspec.LinuxSeccompArg{ + Index: uint(syscallIndex), + Value: syscallValue, + ValueTwo: syscallValueTwo, + Op: syscallOp, + } + + argSlice := []rspec.LinuxSeccompArg{} + argSlice = append(argSlice, argStruct) + return argSlice, nil + } + + return nilArgSlice, fmt.Errorf("incorrect number of arguments passed with syscall: %d", numberOfArgs) +} + +func parseOperator(operator string) (rspec.LinuxSeccompOperator, error) { + operators := map[string]rspec.LinuxSeccompOperator{ + "NE": rspec.OpNotEqual, + "LT": rspec.OpLessThan, + "LE": rspec.OpLessEqual, + "EQ": rspec.OpEqualTo, + "GE": rspec.OpGreaterEqual, + "GT": rspec.OpGreaterThan, + "ME": rspec.OpMaskedEqual, + } + o, ok := operators[operator] + if !ok { + return "", fmt.Errorf("unrecognized operator: %s", operator) + } + return o, nil +} diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_remove.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_remove.go new file mode 100644 index 000000000..59537d49c --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/parse_remove.go @@ -0,0 +1,52 @@ +package seccomp + +import ( + "fmt" + "reflect" + "strings" + + rspec "github.com/opencontainers/runtime-spec/specs-go" +) + +// RemoveAction takes the argument string that was passed with the --remove flag, +// parses it, and updates the Seccomp config accordingly +func RemoveAction(arguments string, config *rspec.LinuxSeccomp) error { + if config == nil { + return fmt.Errorf("Cannot remove action from nil Seccomp pointer") + } + + syscallsToRemove := strings.Split(arguments, ",") + + for counter, syscallStruct := range config.Syscalls { + if reflect.DeepEqual(syscallsToRemove, syscallStruct.Names) { + config.Syscalls = append(config.Syscalls[:counter], config.Syscalls[counter+1:]...) + } + } + + return nil +} + +// RemoveAllSeccompRules removes all seccomp syscall rules +func RemoveAllSeccompRules(config *rspec.LinuxSeccomp) error { + if config == nil { + return fmt.Errorf("Cannot remove action from nil Seccomp pointer") + } + newSyscallSlice := []rspec.LinuxSyscall{} + config.Syscalls = newSyscallSlice + return nil +} + +// RemoveAllMatchingRules will remove any syscall rules that match the specified action +func RemoveAllMatchingRules(config *rspec.LinuxSeccomp, seccompAction rspec.LinuxSeccompAction) error { + if config == nil { + return fmt.Errorf("Cannot remove action from nil Seccomp pointer") + } + + for _, syscall := range config.Syscalls { + if reflect.DeepEqual(syscall.Action, seccompAction) { + RemoveAction(strings.Join(syscall.Names, ","), config) + } + } + + return nil +} diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go new file mode 100644 index 000000000..35b12cd65 --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/seccomp_default.go @@ -0,0 +1,577 @@ +package seccomp + +import ( + "runtime" + "syscall" + + "github.com/opencontainers/runtime-spec/specs-go" + rspec "github.com/opencontainers/runtime-spec/specs-go" +) + +func arches() []rspec.Arch { + native := runtime.GOARCH + + switch native { + case "amd64": + return []rspec.Arch{rspec.ArchX86_64, rspec.ArchX86, rspec.ArchX32} + case "arm64": + return []rspec.Arch{rspec.ArchARM, rspec.ArchAARCH64} + case "mips64": + return []rspec.Arch{rspec.ArchMIPS, rspec.ArchMIPS64, rspec.ArchMIPS64N32} + case "mips64n32": + return []rspec.Arch{rspec.ArchMIPS, rspec.ArchMIPS64, rspec.ArchMIPS64N32} + case "mipsel64": + return []rspec.Arch{rspec.ArchMIPSEL, rspec.ArchMIPSEL64, rspec.ArchMIPSEL64N32} + case "mipsel64n32": + return []rspec.Arch{rspec.ArchMIPSEL, rspec.ArchMIPSEL64, rspec.ArchMIPSEL64N32} + case "s390x": + return []rspec.Arch{rspec.ArchS390, rspec.ArchS390X} + default: + return []rspec.Arch{} + } +} + +// DefaultProfile defines the whitelist for the default seccomp profile. +func DefaultProfile(rs *specs.Spec) *rspec.LinuxSeccomp { + + syscalls := []rspec.LinuxSyscall{ + { + Names: []string{ + "accept", + "accept4", + "access", + "alarm", + "bind", + "brk", + "capget", + "capset", + "chdir", + "chmod", + "chown", + "chown32", + "clock_getres", + "clock_gettime", + "clock_nanosleep", + "close", + "connect", + "copy_file_range", + "creat", + "dup", + "dup2", + "dup3", + "epoll_create", + "epoll_create1", + "epoll_ctl", + "epoll_ctl_old", + "epoll_pwait", + "epoll_wait", + "epoll_wait_old", + "eventfd", + "eventfd2", + "execve", + "execveat", + "exit", + "exit_group", + "faccessat", + "fadvise64", + "fadvise64_64", + "fallocate", + "fanotify_mark", + "fchdir", + "fchmod", + "fchmodat", + "fchown", + "fchown32", + "fchownat", + "fcntl", + "fcntl64", + "fdatasync", + "fgetxattr", + "flistxattr", + "flock", + "fork", + "fremovexattr", + "fsetxattr", + "fstat", + "fstat64", + "fstatat64", + "fstatfs", + "fstatfs64", + "fsync", + "ftruncate", + "ftruncate64", + "futex", + "futimesat", + "getcpu", + "getcwd", + "getdents", + "getdents64", + "getegid", + "getegid32", + "geteuid", + "geteuid32", + "getgid", + "getgid32", + "getgroups", + "getgroups32", + "getitimer", + "getpeername", + "getpgid", + "getpgrp", + "getpid", + "getppid", + "getpriority", + "getrandom", + "getresgid", + "getresgid32", + "getresuid", + "getresuid32", + "getrlimit", + "get_robust_list", + "getrusage", + "getsid", + "getsockname", + "getsockopt", + "get_thread_area", + "gettid", + "gettimeofday", + "getuid", + "getuid32", + "getxattr", + "inotify_add_watch", + "inotify_init", + "inotify_init1", + "inotify_rm_watch", + "io_cancel", + "ioctl", + "io_destroy", + "io_getevents", + "ioprio_get", + "ioprio_set", + "io_setup", + "io_submit", + "ipc", + "kill", + "lchown", + "lchown32", + "lgetxattr", + "link", + "linkat", + "listen", + "listxattr", + "llistxattr", + "_llseek", + "lremovexattr", + "lseek", + "lsetxattr", + "lstat", + "lstat64", + "madvise", + "memfd_create", + "mincore", + "mkdir", + "mkdirat", + "mknod", + "mknodat", + "mlock", + "mlock2", + "mlockall", + "mmap", + "mmap2", + "mprotect", + "mq_getsetattr", + "mq_notify", + "mq_open", + "mq_timedreceive", + "mq_timedsend", + "mq_unlink", + "mremap", + "msgctl", + "msgget", + "msgrcv", + "msgsnd", + "msync", + "munlock", + "munlockall", + "munmap", + "nanosleep", + "newfstatat", + "_newselect", + "open", + "openat", + "pause", + "pipe", + "pipe2", + "poll", + "ppoll", + "prctl", + "pread64", + "preadv", + "prlimit64", + "pselect6", + "pwrite64", + "pwritev", + "read", + "readahead", + "readlink", + "readlinkat", + "readv", + "recv", + "recvfrom", + "recvmmsg", + "recvmsg", + "remap_file_pages", + "removexattr", + "rename", + "renameat", + "renameat2", + "restart_syscall", + "rmdir", + "rt_sigaction", + "rt_sigpending", + "rt_sigprocmask", + "rt_sigqueueinfo", + "rt_sigreturn", + "rt_sigsuspend", + "rt_sigtimedwait", + "rt_tgsigqueueinfo", + "sched_getaffinity", + "sched_getattr", + "sched_getparam", + "sched_get_priority_max", + "sched_get_priority_min", + "sched_getscheduler", + "sched_rr_get_interval", + "sched_setaffinity", + "sched_setattr", + "sched_setparam", + "sched_setscheduler", + "sched_yield", + "seccomp", + "select", + "semctl", + "semget", + "semop", + "semtimedop", + "send", + "sendfile", + "sendfile64", + "sendmmsg", + "sendmsg", + "sendto", + "setfsgid", + "setfsgid32", + "setfsuid", + "setfsuid32", + "setgid", + "setgid32", + "setgroups", + "setgroups32", + "setitimer", + "setpgid", + "setpriority", + "setregid", + "setregid32", + "setresgid", + "setresgid32", + "setresuid", + "setresuid32", + "setreuid", + "setreuid32", + "setrlimit", + "set_robust_list", + "setsid", + "setsockopt", + "set_thread_area", + "set_tid_address", + "setuid", + "setuid32", + "setxattr", + "shmat", + "shmctl", + "shmdt", + "shmget", + "shutdown", + "sigaltstack", + "signalfd", + "signalfd4", + "sigreturn", + "socket", + "socketcall", + "socketpair", + "splice", + "stat", + "stat64", + "statfs", + "statfs64", + "symlink", + "symlinkat", + "sync", + "sync_file_range", + "syncfs", + "sysinfo", + "syslog", + "tee", + "tgkill", + "time", + "timer_create", + "timer_delete", + "timerfd_create", + "timerfd_gettime", + "timerfd_settime", + "timer_getoverrun", + "timer_gettime", + "timer_settime", + "times", + "tkill", + "truncate", + "truncate64", + "ugetrlimit", + "umask", + "uname", + "unlink", + "unlinkat", + "utime", + "utimensat", + "utimes", + "vfork", + "vmsplice", + "wait4", + "waitid", + "waitpid", + "write", + "writev", + }, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + { + Names: []string{"personality"}, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{ + { + Index: 0, + Value: 0x0, + Op: rspec.OpEqualTo, + }, + { + Index: 0, + Value: 0x0008, + Op: rspec.OpEqualTo, + }, + { + Index: 0, + Value: 0xffffffff, + Op: rspec.OpEqualTo, + }, + }, + }, + } + var sysCloneFlagsIndex uint + + capSysAdmin := false + caps := make(map[string]bool) + + for _, cap := range rs.Process.Capabilities.Bounding { + caps[cap] = true + } + for _, cap := range rs.Process.Capabilities.Effective { + caps[cap] = true + } + for _, cap := range rs.Process.Capabilities.Inheritable { + caps[cap] = true + } + for _, cap := range rs.Process.Capabilities.Permitted { + caps[cap] = true + } + for _, cap := range rs.Process.Capabilities.Ambient { + caps[cap] = true + } + + for cap := range caps { + switch cap { + case "CAP_DAC_READ_SEARCH": + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{"open_by_handle_at"}, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + case "CAP_SYS_ADMIN": + capSysAdmin = true + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{ + "bpf", + "clone", + "fanotify_init", + "lookup_dcookie", + "mount", + "name_to_handle_at", + "perf_event_open", + "setdomainname", + "sethostname", + "setns", + "umount", + "umount2", + "unshare", + }, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + case "CAP_SYS_BOOT": + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{"reboot"}, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + case "CAP_SYS_CHROOT": + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{"chroot"}, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + case "CAP_SYS_MODULE": + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{ + "delete_module", + "init_module", + "finit_module", + "query_module", + }, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + case "CAP_SYS_PACCT": + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{"acct"}, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + case "CAP_SYS_PTRACE": + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{ + "kcmp", + "process_vm_readv", + "process_vm_writev", + "ptrace", + }, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + case "CAP_SYS_RAWIO": + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{ + "iopl", + "ioperm", + }, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + case "CAP_SYS_TIME": + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{ + "settimeofday", + "stime", + "adjtimex", + }, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + case "CAP_SYS_TTY_CONFIG": + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{"vhangup"}, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + } + } + + if !capSysAdmin { + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{"clone"}, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{ + { + Index: sysCloneFlagsIndex, + Value: syscall.CLONE_NEWNS | syscall.CLONE_NEWUTS | syscall.CLONE_NEWIPC | syscall.CLONE_NEWUSER | syscall.CLONE_NEWPID | syscall.CLONE_NEWNET, + ValueTwo: 0, + Op: rspec.OpMaskedEqual, + }, + }, + }, + }...) + + } + + arch := runtime.GOARCH + switch arch { + case "arm", "arm64": + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{ + "breakpoint", + "cacheflush", + "set_tls", + }, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + case "amd64", "x32": + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{"arch_prctl"}, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + fallthrough + case "x86": + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{"modify_ldt"}, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + case "s390", "s390x": + syscalls = append(syscalls, []rspec.LinuxSyscall{ + { + Names: []string{ + "s390_pci_mmio_read", + "s390_pci_mmio_write", + "s390_runtime_instr", + }, + Action: rspec.ActAllow, + Args: []rspec.LinuxSeccompArg{}, + }, + }...) + /* Flags parameter of the clone syscall is the 2nd on s390 */ + } + + return &rspec.LinuxSeccomp{ + DefaultAction: rspec.ActErrno, + Architectures: arches(), + Syscalls: syscalls, + } +} diff --git a/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go new file mode 100644 index 000000000..dbf2aec1c --- /dev/null +++ b/vendor/github.com/opencontainers/runtime-tools/generate/seccomp/syscall_compare.go @@ -0,0 +1,140 @@ +package seccomp + +import ( + "fmt" + "reflect" + "strconv" + "strings" + + rspec "github.com/opencontainers/runtime-spec/specs-go" +) + +// Determine if a new syscall rule should be appended, overwrite an existing rule +// or if no action should be taken at all +func decideCourseOfAction(newSyscall *rspec.LinuxSyscall, syscalls []rspec.LinuxSyscall) (string, error) { + ruleForSyscallAlreadyExists := false + + var sliceOfDeterminedActions []string + for i, syscall := range syscalls { + if sameName(&syscall, newSyscall) { + ruleForSyscallAlreadyExists = true + + if identical(newSyscall, &syscall) { + sliceOfDeterminedActions = append(sliceOfDeterminedActions, nothing) + } + + if sameAction(newSyscall, &syscall) { + if bothHaveArgs(newSyscall, &syscall) { + sliceOfDeterminedActions = append(sliceOfDeterminedActions, seccompAppend) + } + if onlyOneHasArgs(newSyscall, &syscall) { + if firstParamOnlyHasArgs(newSyscall, &syscall) { + sliceOfDeterminedActions = append(sliceOfDeterminedActions, "overwrite:"+strconv.Itoa(i)) + } else { + sliceOfDeterminedActions = append(sliceOfDeterminedActions, nothing) + } + } + } + + if !sameAction(newSyscall, &syscall) { + if bothHaveArgs(newSyscall, &syscall) { + if sameArgs(newSyscall, &syscall) { + sliceOfDeterminedActions = append(sliceOfDeterminedActions, "overwrite:"+strconv.Itoa(i)) + } + if !sameArgs(newSyscall, &syscall) { + sliceOfDeterminedActions = append(sliceOfDeterminedActions, seccompAppend) + } + } + if onlyOneHasArgs(newSyscall, &syscall) { + sliceOfDeterminedActions = append(sliceOfDeterminedActions, seccompAppend) + } + if neitherHasArgs(newSyscall, &syscall) { + sliceOfDeterminedActions = append(sliceOfDeterminedActions, "overwrite:"+strconv.Itoa(i)) + } + } + } + } + + if !ruleForSyscallAlreadyExists { + sliceOfDeterminedActions = append(sliceOfDeterminedActions, seccompAppend) + } + + // Nothing has highest priority + for _, determinedAction := range sliceOfDeterminedActions { + if determinedAction == nothing { + return determinedAction, nil + } + } + + // Overwrite has second highest priority + for _, determinedAction := range sliceOfDeterminedActions { + if strings.Contains(determinedAction, seccompOverwrite) { + return determinedAction, nil + } + } + + // Append has the lowest priority + for _, determinedAction := range sliceOfDeterminedActions { + if determinedAction == seccompAppend { + return determinedAction, nil + } + } + + return "", fmt.Errorf("Trouble determining action: %s", sliceOfDeterminedActions) +} + +func hasArguments(config *rspec.LinuxSyscall) bool { + nilSyscall := new(rspec.LinuxSyscall) + return !sameArgs(nilSyscall, config) +} + +func identical(config1, config2 *rspec.LinuxSyscall) bool { + return reflect.DeepEqual(config1, config2) +} + +func identicalExceptAction(config1, config2 *rspec.LinuxSyscall) bool { + samename := sameName(config1, config2) + sameAction := sameAction(config1, config2) + sameArgs := sameArgs(config1, config2) + + return samename && !sameAction && sameArgs +} + +func identicalExceptArgs(config1, config2 *rspec.LinuxSyscall) bool { + samename := sameName(config1, config2) + sameAction := sameAction(config1, config2) + sameArgs := sameArgs(config1, config2) + + return samename && sameAction && !sameArgs +} + +func sameName(config1, config2 *rspec.LinuxSyscall) bool { + return reflect.DeepEqual(config1.Names, config2.Names) +} + +func sameAction(config1, config2 *rspec.LinuxSyscall) bool { + return config1.Action == config2.Action +} + +func sameArgs(config1, config2 *rspec.LinuxSyscall) bool { + return reflect.DeepEqual(config1.Args, config2.Args) +} + +func bothHaveArgs(config1, config2 *rspec.LinuxSyscall) bool { + return hasArguments(config1) && hasArguments(config2) +} + +func onlyOneHasArgs(config1, config2 *rspec.LinuxSyscall) bool { + conf1 := hasArguments(config1) + conf2 := hasArguments(config2) + + return (conf1 && !conf2) || (!conf1 && conf2) +} + +func neitherHasArgs(config1, config2 *rspec.LinuxSyscall) bool { + return !hasArguments(config1) && !hasArguments(config2) +} + +func firstParamOnlyHasArgs(config1, config2 *rspec.LinuxSyscall) bool { + return !hasArguments(config1) && hasArguments(config2) +} |