diff --git a/cmd/oci-runtime-tool/generate.go b/cmd/oci-runtime-tool/generate.go index b4c38c8d7..63cd4213e 100644 --- a/cmd/oci-runtime-tool/generate.go +++ b/cmd/oci-runtime-tool/generate.go @@ -9,6 +9,7 @@ import ( rspec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" + "github.com/opencontainers/runtime-tools/generate/seccomp" "github.com/urfave/cli" ) @@ -60,11 +61,17 @@ var generateFlags = []cli.Flag{ cli.BoolFlag{Name: "read-only", Usage: "make the container's rootfs read-only"}, cli.StringFlag{Name: "root-propagation", Usage: "mount propagation for root"}, cli.StringFlag{Name: "rootfs", Value: "rootfs", Usage: "path to the rootfs"}, - cli.StringSliceFlag{Name: "seccomp-arch", Usage: "specifies Additional architectures permitted to be used for system calls"}, - cli.StringSliceFlag{Name: "seccomp-allow", Usage: "specifies syscalls to be added to allowed"}, - cli.StringFlag{Name: "seccomp-default", Usage: "specifies the the defaultaction of Seccomp syscall restrictions"}, - cli.StringSliceFlag{Name: "seccomp-errno", Usage: "specifies syscalls to be added to list that returns an error"}, - cli.StringSliceFlag{Name: "seccomp-syscalls", Usage: "specifies Additional architectures permitted to be used for system calls, e.g Name:Action:Arg1_index/Arg1_value/Arg1_valuetwo/Arg1_op, Arg2_index/Arg2_value/Arg2_valuetwo/Arg2_op "}, + cli.StringFlag{Name: "seccomp-allow", Usage: "specifies syscalls to respond with allow"}, + cli.StringFlag{Name: "seccomp-arch", Usage: "specifies additional architectures permitted to be used for system calls"}, + cli.StringFlag{Name: "seccomp-default", Usage: "specifies default action to be used for system calls and removes existing rules with specified action"}, + cli.StringFlag{Name: "seccomp-default-force", Usage: "same as seccomp-default but does not remove existing rules with specified action"}, + cli.StringFlag{Name: "seccomp-errno", Usage: "specifies syscalls to respond with errno"}, + cli.StringFlag{Name: "seccomp-kill", Usage: "specifies syscalls to respond with kill"}, + cli.BoolFlag{Name: "seccomp-only", Usage: "specifies to export just a seccomp configuration file"}, + cli.StringFlag{Name: "seccomp-remove", Usage: "specifies syscalls to remove seccomp rules for"}, + cli.BoolFlag{Name: "seccomp-remove-all", Usage: "removes all syscall rules from seccomp configuration"}, + cli.StringFlag{Name: "seccomp-trace", Usage: "specifies syscalls to respond with trace"}, + cli.StringFlag{Name: "seccomp-trap", Usage: "specifies syscalls to respond with trap"}, cli.StringFlag{Name: "selinux-label", Usage: "process selinux label"}, cli.StringSliceFlag{Name: "sysctl", Usage: "add sysctl settings e.g net.ipv4.forward=1"}, cli.StringFlag{Name: "template", Usage: "base template to use for creating the configuration"}, @@ -102,11 +109,13 @@ var generateCommand = cli.Command{ return err } + var exportOpts generate.ExportOptions + exportOpts.Seccomp = context.Bool("seccomp-only") + if context.IsSet("output") { - output := context.String("output") - err = specgen.SaveToFile(output) + err = specgen.SaveToFile(context.String("output"), exportOpts) } else { - err = specgen.Save(os.Stdout) + err = specgen.Save(os.Stdout, exportOpts) } if err != nil { return err @@ -395,69 +404,8 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { g.SetLinuxResourcesMemorySwappiness(context.Uint64("linux-mem-swappiness")) } - if context.IsSet("linux-pids-limit") { - g.SetLinuxResourcesPidsLimit(context.Int64("linux-pids-limit")) - } - - var sd string - var sa, ss []string - - if context.IsSet("seccomp-default") { - sd = context.String("seccomp-default") - } - - if context.IsSet("seccomp-arch") { - sa = context.StringSlice("seccomp-arch") - } - - if context.IsSet("seccomp-syscalls") { - ss = context.StringSlice("seccomp-syscalls") - } - - if sd == "" && len(sa) == 0 && len(ss) == 0 { - return nil - } - - // Set the DefaultAction of seccomp - if context.IsSet("seccomp-default") { - if err := g.SetLinuxSeccompDefault(sd); err != nil { - return err - } - } - - // Add the additional architectures permitted to be used for system calls - if context.IsSet("seccomp-arch") { - for _, arch := range sa { - if err := g.AddLinuxSeccompArch(arch); err != nil { - return err - } - } - } - - // Set syscall restrict in Seccomp - if context.IsSet("seccomp-syscalls") { - for _, syscall := range ss { - if err := g.AddLinuxSeccompSyscall(syscall); err != nil { - return err - } - } - } - - if context.IsSet("seccomp-allow") { - seccompAllows := context.StringSlice("seccomp-allow") - for _, s := range seccompAllows { - g.AddLinuxSeccompSyscallAllow(s) - } - } - - if context.IsSet("seccomp-errno") { - seccompErrnos := context.StringSlice("seccomp-errno") - for _, s := range seccompErrnos { - g.AddLinuxSeccompSyscallErrno(s) - } - } - - return nil + err := addSeccomp(context, g) + return err } func setupLinuxNamespaces(context *cli.Context, g *generate.Generator, needsNewUser bool) { @@ -543,3 +491,120 @@ func parseBindMount(s string) (string, string, string, error) { return source, dest, options, nil } + +func addSeccomp(context *cli.Context, g *generate.Generator) error { + + // Set the DefaultAction of seccomp + if context.IsSet("seccomp-default") { + seccompDefault := context.String("seccomp-default") + err := g.SetDefaultSeccompAction(seccompDefault) + if err != nil { + return err + } + } else if context.IsSet("seccomp-default-force") { + seccompDefaultForced := context.String("seccomp-default-force") + err := g.SetDefaultSeccompActionForce(seccompDefaultForced) + if err != nil { + return err + } + } + + // Add the additional architectures permitted to be used for system calls + if context.IsSet("seccomp-arch") { + seccompArch := context.String("seccomp-arch") + architectureArgs := strings.Split(seccompArch, ",") + for _, arg := range architectureArgs { + err := g.SetSeccompArchitecture(arg) + if err != nil { + return err + } + } + } + + if context.IsSet("seccomp-errno") { + err := seccompSet(context, "errno", g) + if err != nil { + return err + } + } + + if context.IsSet("seccomp-kill") { + err := seccompSet(context, "kill", g) + if err != nil { + return err + } + } + + if context.IsSet("seccomp-trace") { + err := seccompSet(context, "trace", g) + if err != nil { + return err + } + } + + if context.IsSet("seccomp-trap") { + err := seccompSet(context, "trap", g) + if err != nil { + return err + } + } + + if context.IsSet("seccomp-allow") { + err := seccompSet(context, "allow", g) + if err != nil { + return err + } + } + + if context.IsSet("seccomp-remove") { + seccompRemove := context.String("seccomp-remove") + err := g.RemoveSeccompRule(seccompRemove) + if err != nil { + return err + } + } + + if context.IsSet("seccomp-remove-all") { + err := g.RemoveAllSeccompRules() + if err != nil { + return err + } + } + return nil +} + +func seccompSet(context *cli.Context, seccompFlag string, g *generate.Generator) error { + flagInput := context.String("seccomp-" + seccompFlag) + flagArgs := strings.Split(flagInput, ",") + setSyscallArgsSlice := []seccomp.SyscallOpts{} + for _, flagArg := range flagArgs { + comparisonArgs := strings.Split(flagArg, ":") + if len(comparisonArgs) == 5 { + setSyscallArgs := seccomp.SyscallOpts{ + Action: seccompFlag, + Syscall: comparisonArgs[0], + Index: comparisonArgs[1], + Value: comparisonArgs[2], + ValueTwo: comparisonArgs[3], + Operator: comparisonArgs[4], + } + setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs) + } else if len(comparisonArgs) == 1 { + setSyscallArgs := seccomp.SyscallOpts{ + Action: seccompFlag, + Syscall: comparisonArgs[0], + } + setSyscallArgsSlice = append(setSyscallArgsSlice, setSyscallArgs) + } else { + return fmt.Errorf("invalid syscall argument formatting %v", comparisonArgs) + } + + for _, r := range setSyscallArgsSlice { + err := g.SetSyscallAction(r) + if err != nil { + return err + } + } + } + return nil +} diff --git a/completions/bash/oci-runtime-tool b/completions/bash/oci-runtime-tool index fa6c45aee..389c6a40f 100644 --- a/completions/bash/oci-runtime-tool +++ b/completions/bash/oci-runtime-tool @@ -302,7 +302,14 @@ _oci-runtime-tool_generate() { --seccomp-allow --seccomp-arch --seccomp-default + --seccomp-default-force --seccomp-errno + --seccomp-kill + --seccomp-only + --seccomp-remove + --seccomp-remove-all + --seccomp-trace + --seccomp-trap --seccomp-syscalls --selinux-label --sysctl diff --git a/generate/generate.go b/generate/generate.go index 4892410fc..b4530b5e5 100644 --- a/generate/generate.go +++ b/generate/generate.go @@ -7,10 +7,10 @@ import ( "io" "os" "runtime" - "strconv" "strings" rspec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/opencontainers/runtime-tools/generate/seccomp" "github.com/syndtr/gocapability/capability" ) @@ -25,6 +25,11 @@ type Generator struct { HostSpecific bool } +// ExportOptions have toggles for exporting only certain parts of the specification +type ExportOptions struct { + Seccomp bool // seccomp toggles if only seccomp should be exported +} + // New creates a spec Generator with the default spec. func New() Generator { spec := rspec.Spec{ @@ -140,6 +145,7 @@ func New() Generator { Devices: []rspec.Device{}, }, } + spec.Linux.Seccomp = seccomp.DefaultProfile(&spec) return Generator{ spec: &spec, } @@ -187,8 +193,14 @@ func (g *Generator) Spec() *rspec.Spec { } // Save writes the spec into w. -func (g *Generator) Save(w io.Writer) error { - data, err := json.MarshalIndent(g.spec, "", "\t") +func (g *Generator) Save(w io.Writer, exportOpts ExportOptions) (err error) { + var data []byte + + if exportOpts.Seccomp { + data, err = json.MarshalIndent(g.spec.Linux.Seccomp, "", "\t") + } else { + data, err = json.MarshalIndent(g.spec, "", "\t") + } if err != nil { return err } @@ -202,13 +214,13 @@ func (g *Generator) Save(w io.Writer) error { } // SaveToFile writes the spec into a file. -func (g *Generator) SaveToFile(path string) error { +func (g *Generator) SaveToFile(path string, exportOpts ExportOptions) error { f, err := os.Create(path) if err != nil { return err } defer f.Close() - return g.Save(f) + return g.Save(f, exportOpts) } // SetVersion sets g.spec.Version. @@ -480,278 +492,6 @@ func (g *Generator) RemoveLinuxSysctl(key string) { delete(g.spec.Linux.Sysctl, key) } -// SetLinuxSeccompDefault sets g.spec.Linux.Seccomp.DefaultAction. -func (g *Generator) SetLinuxSeccompDefault(sdefault string) error { - switch sdefault { - case "": - case "SCMP_ACT_KILL": - case "SCMP_ACT_TRAP": - case "SCMP_ACT_ERRNO": - case "SCMP_ACT_TRACE": - case "SCMP_ACT_ALLOW": - default: - return fmt.Errorf("seccomp-default must be empty or one of " + - "SCMP_ACT_KILL|SCMP_ACT_TRAP|SCMP_ACT_ERRNO|SCMP_ACT_TRACE|" + - "SCMP_ACT_ALLOW") - } - - g.initSpecLinuxSeccomp() - g.spec.Linux.Seccomp.DefaultAction = rspec.Action(sdefault) - return nil -} - -func checkSeccompArch(arch string) error { - switch arch { - case "": - case "SCMP_ARCH_X86": - case "SCMP_ARCH_X86_64": - case "SCMP_ARCH_X32": - case "SCMP_ARCH_ARM": - case "SCMP_ARCH_AARCH64": - case "SCMP_ARCH_MIPS": - case "SCMP_ARCH_MIPS64": - case "SCMP_ARCH_MIPS64N32": - case "SCMP_ARCH_MIPSEL": - case "SCMP_ARCH_MIPSEL64": - case "SCMP_ARCH_MIPSEL64N32": - default: - return fmt.Errorf("seccomp-arch must be empty or one of " + - "SCMP_ARCH_X86|SCMP_ARCH_X86_64|SCMP_ARCH_X32|SCMP_ARCH_ARM|" + - "SCMP_ARCH_AARCH64SCMP_ARCH_MIPS|SCMP_ARCH_MIPS64|" + - "SCMP_ARCH_MIPS64N32|SCMP_ARCH_MIPSEL|SCMP_ARCH_MIPSEL64|" + - "SCMP_ARCH_MIPSEL64N32") - } - return nil -} - -// ClearLinuxSeccompArch clears g.spec.Linux.Seccomp.Architectures. -func (g *Generator) ClearLinuxSeccompArch() { - if g.spec == nil || g.spec.Linux == nil || g.spec.Linux.Seccomp == nil { - return - } - - g.spec.Linux.Seccomp.Architectures = []rspec.Arch{} -} - -// AddLinuxSeccompArch adds sArch into g.spec.Linux.Seccomp.Architectures. -func (g *Generator) AddLinuxSeccompArch(sArch string) error { - if err := checkSeccompArch(sArch); err != nil { - return err - } - - g.initSpecLinuxSeccomp() - g.spec.Linux.Seccomp.Architectures = append(g.spec.Linux.Seccomp.Architectures, rspec.Arch(sArch)) - - return nil -} - -// RemoveSeccompArch removes sArch from g.spec.Linux.Seccomp.Architectures. -func (g *Generator) RemoveSeccompArch(sArch string) error { - if err := checkSeccompArch(sArch); err != nil { - return err - } - - if g.spec == nil || g.spec.Linux == nil || g.spec.Linux.Seccomp == nil { - return nil - } - - for i, arch := range g.spec.Linux.Seccomp.Architectures { - if string(arch) == sArch { - g.spec.Linux.Seccomp.Architectures = append(g.spec.Linux.Seccomp.Architectures[:i], g.spec.Linux.Seccomp.Architectures[i+1:]...) - return nil - } - } - - return nil -} - -func checkSeccompSyscallAction(syscall string) error { - switch syscall { - case "": - case "SCMP_ACT_KILL": - case "SCMP_ACT_TRAP": - case "SCMP_ACT_ERRNO": - case "SCMP_ACT_TRACE": - case "SCMP_ACT_ALLOW": - default: - return fmt.Errorf("seccomp-syscall action must be empty or " + - "one of SCMP_ACT_KILL|SCMP_ACT_TRAP|SCMP_ACT_ERRNO|" + - "SCMP_ACT_TRACE|SCMP_ACT_ALLOW") - } - return nil -} - -func checkSeccompSyscallArg(arg string) error { - switch arg { - case "": - case "SCMP_CMP_NE": - case "SCMP_CMP_LT": - case "SCMP_CMP_LE": - case "SCMP_CMP_EQ": - case "SCMP_CMP_GE": - case "SCMP_CMP_GT": - case "SCMP_CMP_MASKED_EQ": - default: - return fmt.Errorf("seccomp-syscall args must be " + - "empty or one of SCMP_CMP_NE|SCMP_CMP_LT|" + - "SCMP_CMP_LE|SCMP_CMP_EQ|SCMP_CMP_GE|" + - "SCMP_CMP_GT|SCMP_CMP_MASKED_EQ") - } - return nil -} - -func parseSeccompSyscall(s string) (rspec.Syscall, error) { - syscall := strings.Split(s, ":") - if len(syscall) != 3 { - return rspec.Syscall{}, fmt.Errorf("seccomp sysctl must consist of 3 parameters") - } - name := syscall[0] - if err := checkSeccompSyscallAction(syscall[1]); err != nil { - return rspec.Syscall{}, err - } - action := rspec.Action(syscall[1]) - - var Args []rspec.Arg - if strings.EqualFold(syscall[2], "") { - Args = nil - } else { - argsslice := strings.Split(syscall[2], ",") - for _, argsstru := range argsslice { - args := strings.Split(argsstru, "/") - if len(args) == 4 { - index, err := strconv.Atoi(args[0]) - value, err := strconv.Atoi(args[1]) - value2, err := strconv.Atoi(args[2]) - if err != nil { - return rspec.Syscall{}, err - } - if err := checkSeccompSyscallArg(args[3]); err != nil { - return rspec.Syscall{}, err - } - op := rspec.Operator(args[3]) - Arg := rspec.Arg{ - Index: uint(index), - Value: uint64(value), - ValueTwo: uint64(value2), - Op: op, - } - Args = append(Args, Arg) - } else { - return rspec.Syscall{}, fmt.Errorf("seccomp-sysctl args error: %s", argsstru) - } - } - } - - return rspec.Syscall{ - Name: name, - Action: action, - Args: Args, - }, nil -} - -// ClearLinuxSeccompSyscall clears g.spec.Linux.Seccomp.Syscalls. -func (g *Generator) ClearLinuxSeccompSyscall() { - if g.spec == nil || g.spec.Linux == nil || g.spec.Linux.Seccomp == nil { - return - } - - g.spec.Linux.Seccomp.Syscalls = []rspec.Syscall{} -} - -// AddLinuxSeccompSyscall adds sSyscall into g.spec.Linux.Seccomp.Syscalls. -func (g *Generator) AddLinuxSeccompSyscall(sSyscall string) error { - f, err := parseSeccompSyscall(sSyscall) - if err != nil { - return err - } - - g.initSpecLinuxSeccomp() - g.spec.Linux.Seccomp.Syscalls = append(g.spec.Linux.Seccomp.Syscalls, f) - return nil -} - -// AddLinuxSeccompSyscallAllow adds seccompAllow into g.spec.Linux.Seccomp.Syscalls. -func (g *Generator) AddLinuxSeccompSyscallAllow(seccompAllow string) { - syscall := rspec.Syscall{ - Name: seccompAllow, - Action: "SCMP_ACT_ALLOW", - } - - g.initSpecLinuxSeccomp() - g.spec.Linux.Seccomp.Syscalls = append(g.spec.Linux.Seccomp.Syscalls, syscall) -} - -// AddLinuxSeccompSyscallErrno adds seccompErrno into g.spec.Linux.Seccomp.Syscalls. -func (g *Generator) AddLinuxSeccompSyscallErrno(seccompErrno string) { - syscall := rspec.Syscall{ - Name: seccompErrno, - Action: "SCMP_ACT_ERRNO", - } - - g.initSpecLinuxSeccomp() - g.spec.Linux.Seccomp.Syscalls = append(g.spec.Linux.Seccomp.Syscalls, syscall) -} - -// RemoveSeccompSyscallByName removes all the seccomp syscalls with the given -// name from g.spec.Linux.Seccomp.Syscalls. -func (g *Generator) RemoveSeccompSyscallByName(name string) error { - if g.spec == nil || g.spec.Linux == nil || g.spec.Linux.Seccomp == nil { - return nil - } - - var r []rspec.Syscall - for _, syscall := range g.spec.Linux.Seccomp.Syscalls { - if strings.Compare(name, syscall.Name) != 0 { - r = append(r, syscall) - } - } - g.spec.Linux.Seccomp.Syscalls = r - return nil -} - -// RemoveSeccompSyscallByAction removes all the seccomp syscalls with the given -// action from g.spec.Linux.Seccomp.Syscalls. -func (g *Generator) RemoveSeccompSyscallByAction(action string) error { - if g.spec == nil || g.spec.Linux == nil || g.spec.Linux.Seccomp == nil { - return nil - } - - if err := checkSeccompSyscallAction(action); err != nil { - return err - } - - var r []rspec.Syscall - for _, syscall := range g.spec.Linux.Seccomp.Syscalls { - if strings.Compare(action, string(syscall.Action)) != 0 { - r = append(r, syscall) - } - } - g.spec.Linux.Seccomp.Syscalls = r - return nil -} - -// RemoveSeccompSyscall removes all the seccomp syscalls with the given -// name and action from g.spec.Linux.Seccomp.Syscalls. -func (g *Generator) RemoveSeccompSyscall(name string, action string) error { - if g.spec == nil || g.spec.Linux == nil || g.spec.Linux.Seccomp == nil { - return nil - } - - if err := checkSeccompSyscallAction(action); err != nil { - return err - } - - var r []rspec.Syscall - for _, syscall := range g.spec.Linux.Seccomp.Syscalls { - if !(strings.Compare(name, syscall.Name) == 0 && - strings.Compare(action, string(syscall.Action)) == 0) { - r = append(r, syscall) - } - } - g.spec.Linux.Seccomp.Syscalls = r - return nil -} - // ClearLinuxUIDMappings clear g.spec.Linux.UIDMappings. func (g *Generator) ClearLinuxUIDMappings() { if g.spec == nil || g.spec.Linux == nil { @@ -1075,42 +815,39 @@ func (g *Generator) RemoveLinuxNamespace(ns string) error { // strPtr returns the pointer pointing to the string s. func strPtr(s string) *string { return &s } -// FIXME: this function is not used. -func parseArgs(args2parse string) ([]*rspec.Arg, error) { - var Args []*rspec.Arg - argstrslice := strings.Split(args2parse, ",") - for _, argstr := range argstrslice { - args := strings.Split(argstr, "/") - if len(args) == 4 { - index, err := strconv.Atoi(args[0]) - value, err := strconv.Atoi(args[1]) - value2, err := strconv.Atoi(args[2]) - if err != nil { - return nil, err - } - switch args[3] { - case "": - case "SCMP_CMP_NE": - case "SCMP_CMP_LT": - case "SCMP_CMP_LE": - case "SCMP_CMP_EQ": - case "SCMP_CMP_GE": - case "SCMP_CMP_GT": - case "SCMP_CMP_MASKED_EQ": - default: - return nil, fmt.Errorf("seccomp-sysctl args must be empty or one of SCMP_CMP_NE|SCMP_CMP_LT|SCMP_CMP_LE|SCMP_CMP_EQ|SCMP_CMP_GE|SCMP_CMP_GT|SCMP_CMP_MASKED_EQ") - } - op := rspec.Operator(args[3]) - Arg := rspec.Arg{ - Index: uint(index), - Value: uint64(value), - ValueTwo: uint64(value2), - Op: op, - } - Args = append(Args, &Arg) - } else { - return nil, fmt.Errorf("seccomp-sysctl args error: %s", argstr) - } - } - return Args, nil +// SetSyscallAction adds rules for syscalls with the specified action +func (g *Generator) SetSyscallAction(arguments seccomp.SyscallOpts) error { + g.initSpecLinuxSeccomp() + return seccomp.ParseSyscallFlag(arguments, g.spec.Linux.Seccomp) +} + +// SetDefaultSeccompAction sets the default action for all syscalls not defined +// and then removes any syscall rules with this action already specified. +func (g *Generator) SetDefaultSeccompAction(action string) error { + g.initSpecLinuxSeccomp() + return seccomp.ParseDefaultAction(action, g.spec.Linux.Seccomp) +} + +// SetDefaultSeccompActionForce only sets the default action for all syscalls not defined +func (g *Generator) SetDefaultSeccompActionForce(action string) error { + g.initSpecLinuxSeccomp() + return seccomp.ParseDefaultActionForce(action, g.spec.Linux.Seccomp) +} + +// SetSeccompArchitecture sets the supported seccomp architectures +func (g *Generator) SetSeccompArchitecture(architecture string) error { + g.initSpecLinuxSeccomp() + return seccomp.ParseArchitectureFlag(architecture, g.spec.Linux.Seccomp) +} + +// RemoveSeccompRule removes rules for any specified syscalls +func (g *Generator) RemoveSeccompRule(arguments string) error { + g.initSpecLinuxSeccomp() + return seccomp.RemoveAction(arguments, g.spec.Linux.Seccomp) +} + +// RemoveAllSeccompRules removes all syscall rules +func (g *Generator) RemoveAllSeccompRules() error { + g.initSpecLinuxSeccomp() + return seccomp.RemoveAllSeccompRules(g.spec.Linux.Seccomp) } diff --git a/generate/seccomp/consts.go b/generate/seccomp/consts.go new file mode 100644 index 000000000..eade5718e --- /dev/null +++ b/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/generate/seccomp/doc.go b/generate/seccomp/doc.go deleted file mode 100644 index 481bd7004..000000000 --- a/generate/seccomp/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package seccomp includes functions for configuring seccomp. -package seccomp diff --git a/generate/seccomp/parse_action.go b/generate/seccomp/parse_action.go new file mode 100644 index 000000000..13cace24f --- /dev/null +++ b/generate/seccomp/parse_action.go @@ -0,0 +1,127 @@ +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.Seccomp) 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 { + return fmt.Errorf("default action already set as %s", action) + } + + var newSyscall rspec.Syscall + 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.Action{ + "allow": rspec.ActAllow, + "errno": rspec.ActErrno, + "kill": rspec.ActKill, + "trace": rspec.ActTrace, + "trap": rspec.ActTrap, +} + +// Take passed action, return the SCMP_ACT_ version of it +func parseAction(action string) (rspec.Action, 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.Seccomp) error { + if action == "" { + return nil + } + + defaultAction, err := parseAction(action) + if err != nil { + return err + } + config.DefaultAction = defaultAction + err = RemoveAllMatchingRules(config, action) + if err != nil { + return err + } + return nil +} + +// ParseDefaultActionForce simply sets the default action of the seccomp configuration +func ParseDefaultActionForce(action string, config *rspec.Seccomp) 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.Action, args []rspec.Arg) rspec.Syscall { + syscallStruct := rspec.Syscall{ + Name: name, + Action: action, + Args: args, + } + return syscallStruct +} diff --git a/generate/seccomp/parse_architecture.go b/generate/seccomp/parse_architecture.go new file mode 100644 index 000000000..9d45fabc6 --- /dev/null +++ b/generate/seccomp/parse_architecture.go @@ -0,0 +1,53 @@ +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.Seccomp) 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, + "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/generate/seccomp/parse_arguments.go b/generate/seccomp/parse_arguments.go new file mode 100644 index 000000000..72f0b13d8 --- /dev/null +++ b/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.Arg, error) { + nilArgSlice := []rspec.Arg{} + 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.Arg{ + Index: uint(syscallIndex), + Value: syscallValue, + ValueTwo: syscallValueTwo, + Op: syscallOp, + } + + argSlice := []rspec.Arg{} + 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.Operator, error) { + operators := map[string]rspec.Operator{ + "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/generate/seccomp/parse_remove.go b/generate/seccomp/parse_remove.go new file mode 100644 index 000000000..ce68e66d0 --- /dev/null +++ b/generate/seccomp/parse_remove.go @@ -0,0 +1,68 @@ +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.Seccomp) error { + if config == nil { + return fmt.Errorf("Cannot remove action from nil Seccomp pointer") + } + + var syscallsToRemove []string + if strings.Contains(arguments, ",") { + syscallsToRemove = strings.Split(arguments, ",") + } else { + syscallsToRemove = append(syscallsToRemove, arguments) + } + + for _, syscall := range syscallsToRemove { + for counter, syscallStruct := range config.Syscalls { + if syscallStruct.Name == syscall { + config.Syscalls = append(config.Syscalls[:counter], config.Syscalls[counter+1:]...) + } + } + } + return nil +} + +// RemoveAllSeccompRules removes all seccomp syscall rules +func RemoveAllSeccompRules(config *rspec.Seccomp) error { + if config == nil { + return fmt.Errorf("Cannot remove action from nil Seccomp pointer") + } + newSyscallSlice := []rspec.Syscall{} + config.Syscalls = newSyscallSlice + return nil +} + +// RemoveAllMatchingRules will remove any syscall rules that match the specified action +func RemoveAllMatchingRules(config *rspec.Seccomp, action string) error { + if config == nil { + return fmt.Errorf("Cannot remove action from nil Seccomp pointer") + } + + seccompAction, err := parseAction(action) + if err != nil { + return err + } + + syscallsToRemove := []string{} + for _, syscall := range config.Syscalls { + if reflect.DeepEqual(syscall.Action, seccompAction) { + syscallsToRemove = append(syscallsToRemove, syscall.Name) + } + } + + for i := range syscallsToRemove { + RemoveAction(syscallsToRemove[i], config) + } + + return nil +} diff --git a/generate/seccomp/seccomp_default.go b/generate/seccomp/seccomp_default.go new file mode 100644 index 000000000..2e1d46870 --- /dev/null +++ b/generate/seccomp/seccomp_default.go @@ -0,0 +1,1870 @@ +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.Seccomp { + + syscalls := []rspec.Syscall{ + { + Name: "accept", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "accept4", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "access", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "alarm", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "bind", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "brk", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "capget", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "capset", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "chdir", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "chmod", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "chown", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "chown32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + + { + Name: "clock_getres", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "clock_gettime", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "clock_nanosleep", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "close", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "connect", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "copy_file_range", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "creat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "dup", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "dup2", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "dup3", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "epoll_create", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "epoll_create1", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "epoll_ctl", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "epoll_ctl_old", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "epoll_pwait", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "epoll_wait", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "epoll_wait_old", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "eventfd", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "eventfd2", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "execve", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "execveat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "exit", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "exit_group", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "faccessat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fadvise64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fadvise64_64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fallocate", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fanotify_mark", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fchdir", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fchmod", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fchmodat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fchown", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fchown32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fchownat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fcntl", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fcntl64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fdatasync", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fgetxattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "flistxattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "flock", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fork", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fremovexattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fsetxattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fstat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fstat64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fstatat64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fstatfs", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fstatfs64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fsync", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "ftruncate", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "ftruncate64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "futex", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "futimesat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getcpu", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getcwd", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getdents", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getdents64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getegid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getegid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "geteuid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "geteuid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getgid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getgid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getgroups", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getgroups32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getitimer", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getpeername", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getpgid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getpgrp", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getpid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getppid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getpriority", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getrandom", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getresgid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getresgid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getresuid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getresuid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getrlimit", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "get_robust_list", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getrusage", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getsid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getsockname", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getsockopt", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "get_thread_area", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "gettid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "gettimeofday", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getuid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getuid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "getxattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "inotify_add_watch", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "inotify_init", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "inotify_init1", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "inotify_rm_watch", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "io_cancel", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "ioctl", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "io_destroy", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "io_getevents", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "ioprio_get", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "ioprio_set", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "io_setup", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "io_submit", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "ipc", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "kill", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "lchown", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "lchown32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "lgetxattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "link", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "linkat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "listen", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "listxattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "llistxattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "_llseek", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "lremovexattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "lseek", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "lsetxattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "lstat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "lstat64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "madvise", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "memfd_create", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mincore", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mkdir", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mkdirat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mknod", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mknodat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mlock", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mlock2", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mlockall", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mmap", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mmap2", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mprotect", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mq_getsetattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mq_notify", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mq_open", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mq_timedreceive", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mq_timedsend", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mq_unlink", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mremap", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "msgctl", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "msgget", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "msgrcv", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "msgsnd", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "msync", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "munlock", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "munlockall", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "munmap", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "nanosleep", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "newfstatat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "_newselect", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "open", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "openat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "pause", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "personality", + Action: rspec.ActAllow, + Args: []rspec.Arg{ + { + Index: 0, + Value: 0x0, + Op: rspec.OpEqualTo, + }, + }, + }, + { + Name: "personality", + Action: rspec.ActAllow, + Args: []rspec.Arg{ + { + Index: 0, + Value: 0x0008, + Op: rspec.OpEqualTo, + }, + }, + }, + { + Name: "personality", + Action: rspec.ActAllow, + Args: []rspec.Arg{ + { + Index: 0, + Value: 0xffffffff, + Op: rspec.OpEqualTo, + }, + }, + }, + { + Name: "pipe", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "pipe2", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "poll", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "ppoll", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "prctl", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "pread64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "preadv", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "prlimit64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "pselect6", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "pwrite64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "pwritev", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "read", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "readahead", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "readlink", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "readlinkat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "readv", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "recv", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "recvfrom", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "recvmmsg", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "recvmsg", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "remap_file_pages", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "removexattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "rename", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "renameat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "renameat2", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "restart_syscall", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "rmdir", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "rt_sigaction", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "rt_sigpending", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "rt_sigprocmask", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "rt_sigqueueinfo", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "rt_sigreturn", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "rt_sigsuspend", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "rt_sigtimedwait", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "rt_tgsigqueueinfo", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sched_getaffinity", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sched_getattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sched_getparam", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sched_get_priority_max", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sched_get_priority_min", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sched_getscheduler", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sched_rr_get_interval", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sched_setaffinity", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sched_setattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sched_setparam", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sched_setscheduler", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sched_yield", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "seccomp", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "select", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "semctl", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "semget", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "semop", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "semtimedop", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "send", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sendfile", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sendfile64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sendmmsg", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sendmsg", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sendto", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setfsgid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setfsgid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setfsuid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setfsuid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setgid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setgid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setgroups", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setgroups32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setitimer", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setpgid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setpriority", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setregid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setregid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setresgid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setresgid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setresuid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setresuid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setreuid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setreuid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setrlimit", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "set_robust_list", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setsid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setsockopt", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "set_thread_area", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "set_tid_address", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setuid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setuid32", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setxattr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "shmat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "shmctl", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "shmdt", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "shmget", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "shutdown", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sigaltstack", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "signalfd", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "signalfd4", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sigreturn", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "socket", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "socketcall", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "socketpair", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "splice", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "stat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "stat64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "statfs", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "statfs64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "symlink", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "symlinkat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sync", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sync_file_range", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "syncfs", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sysinfo", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "syslog", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "tee", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "tgkill", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "time", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "timer_create", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "timer_delete", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "timerfd_create", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "timerfd_gettime", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "timerfd_settime", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "timer_getoverrun", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "timer_gettime", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "timer_settime", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "times", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "tkill", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "truncate", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "truncate64", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "ugetrlimit", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "umask", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "uname", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "unlink", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "unlinkat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "utime", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "utimensat", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "utimes", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "vfork", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "vmsplice", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "wait4", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "waitid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "waitpid", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "write", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "writev", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + } + var sysCloneFlagsIndex uint + + capSysAdmin := false + var cap string + + for _, cap = range rs.Process.Capabilities { + switch cap { + case "CAP_DAC_READ_SEARCH": + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "open_by_handle_at", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + case "CAP_SYS_ADMIN": + capSysAdmin = true + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "bpf", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "clone", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "fanotify_init", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "lookup_dcookie", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "mount", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "name_to_handle_at", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "perf_event_open", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setdomainname", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "sethostname", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "setns", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "umount", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "umount2", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "unshare", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + case "CAP_SYS_BOOT": + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "reboot", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + case "CAP_SYS_CHROOT": + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "chroot", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + case "CAP_SYS_MODULE": + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "delete_module", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "init_module", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "finit_module", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "query_module", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + case "CAP_SYS_PACCT": + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "acct", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + case "CAP_SYS_PTRACE": + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "kcmp", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "process_vm_readv", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "process_vm_writev", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "ptrace", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + case "CAP_SYS_RAWIO": + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "iopl", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "ioperm", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + case "CAP_SYS_TIME": + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "settimeofday", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "stime", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "adjtimex", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + case "CAP_SYS_TTY_CONFIG": + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "vhangup", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + } + } + + if !capSysAdmin { + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "clone", + Action: rspec.ActAllow, + Args: []rspec.Arg{ + { + 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.Syscall{ + { + Name: "breakpoint", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "cacheflush", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "set_tls", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + case "amd64", "x32": + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "arch_prctl", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + fallthrough + case "x86": + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "modify_ldt", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + case "s390", "s390x": + syscalls = append(syscalls, []rspec.Syscall{ + { + Name: "s390_pci_mmio_read", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "s390_pci_mmio_write", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + { + Name: "s390_runtime_instr", + Action: rspec.ActAllow, + Args: []rspec.Arg{}, + }, + }...) + /* Flags parameter of the clone syscall is the 2nd on s390 */ + } + + return &rspec.Seccomp{ + DefaultAction: rspec.ActErrno, + Architectures: arches(), + Syscalls: syscalls, + } +} diff --git a/generate/seccomp/syscall_compare.go b/generate/seccomp/syscall_compare.go new file mode 100644 index 000000000..01dc2e30c --- /dev/null +++ b/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.Syscall, syscalls []rspec.Syscall) (string, error) { + ruleForSyscallAlreadyExists := false + + var sliceOfDeterminedActions []string + for i, syscall := range syscalls { + if syscall.Name == newSyscall.Name { + 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.Syscall) bool { + nilSyscall := new(rspec.Syscall) + return !sameArgs(nilSyscall, config) +} + +func identical(config1, config2 *rspec.Syscall) bool { + return reflect.DeepEqual(config1, config2) +} + +func identicalExceptAction(config1, config2 *rspec.Syscall) bool { + samename := sameName(config1, config2) + sameAction := sameAction(config1, config2) + sameArgs := sameArgs(config1, config2) + + return samename && !sameAction && sameArgs +} + +func identicalExceptArgs(config1, config2 *rspec.Syscall) bool { + samename := sameName(config1, config2) + sameAction := sameAction(config1, config2) + sameArgs := sameArgs(config1, config2) + + return samename && sameAction && !sameArgs +} + +func sameName(config1, config2 *rspec.Syscall) bool { + return config1.Name == config2.Name +} + +func sameAction(config1, config2 *rspec.Syscall) bool { + return config1.Action == config2.Action +} + +func sameArgs(config1, config2 *rspec.Syscall) bool { + return reflect.DeepEqual(config1.Args, config2.Args) +} + +func bothHaveArgs(config1, config2 *rspec.Syscall) bool { + return hasArguments(config1) && hasArguments(config2) +} + +func onlyOneHasArgs(config1, config2 *rspec.Syscall) bool { + conf1 := hasArguments(config1) + conf2 := hasArguments(config2) + + return (conf1 && !conf2) || (!conf1 && conf2) +} + +func neitherHasArgs(config1, config2 *rspec.Syscall) bool { + return !hasArguments(config1) && !hasArguments(config2) +} + +func firstParamOnlyHasArgs(config1, config2 *rspec.Syscall) bool { + return !hasArguments(config1) && hasArguments(config2) +} diff --git a/man/oci-runtime-tool-generate.1.md b/man/oci-runtime-tool-generate.1.md index 678c2cc1d..fbc35b629 100644 --- a/man/oci-runtime-tool-generate.1.md +++ b/man/oci-runtime-tool-generate.1.md @@ -215,26 +215,42 @@ read the configuration from `config.json`. **--rootfs**=ROOTFSPATH Path to the rootfs -**--seccomp-arch**=ARCH - Specifies Additional architectures permitted to be used for system calls. - By default if you turn on seccomp, only the host architecture will be allowed. - **--seccomp-allow**=SYSCALL Specifies syscalls to be added to the ALLOW list. See --seccomp-syscalls for setting limits on arguments. +**--seccomp-arch**=ARCH + Specifies Additional architectures permitted to be used for system calls. + By default if you turn on seccomp, only the host architecture will be allowed. + **--seccomp-default**=ACTION + Specifies the the default action of Seccomp syscall restrictions and removes existing restrictions with the specified action + Values: KILL,ERRNO,TRACE,ALLOW + +**--seccomp-default-force**=ACTION Specifies the the default action of Seccomp syscall restrictions Values: KILL,ERRNO,TRACE,ALLOW **--seccomp-errno**=SYSCALL - Specifies syscalls to be added to the ERRNO list. - See --seccomp-syscalls for setting limits on arguments. + Specifies syscalls to create seccomp rule to respond with ERRNO. + +**--seccomp-kill**=SYSCALL + Specifies syscalls to create seccomp rule to respond with KILL. + +**--seccomp-only** + Option to only export the seccomp section of output + +**--seccomp-remove** + Specifies syscall restrictions to remove from the configuration. + +**--seccomp-remove-all** + Option to remove all syscall restrictions. + +**--seccomp-trace**=SYSCALL + Specifies syscalls to create seccomp rule to respond with TRACE. -**--seccomp-syscalls**=SYSCALLS - Specifies Additional syscalls permitted to be used for system calls, - e.g Name:Action:Arg1_index/Arg1_value/Arg1_valuetwo/Arg1_op, Arg2_index/Arg2_value/Arg2_valuetwo/Arg2_op - See --seccomp-allow and --seccomp-errno for convenient way to set seccomp syscall options. +**--seccomp-trap**=SYSCALL + Specifies syscalls to create seccomp rule to respond with TRAP. **--selinux-label**=PROCESSLABEL SELinux Label