Skip to content

Commit

Permalink
Add base syscalls for spoc recording
Browse files Browse the repository at this point in the history
This allows to have a preset of defined syscalls required as a minimum
to run containers with runc and crun.

Signed-off-by: Sascha Grunert <[email protected]>
  • Loading branch information
saschagrunert authored and k8s-ci-robot committed Mar 2, 2023
1 parent ccd2a49 commit 93eed48
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 8 deletions.
13 changes: 13 additions & 0 deletions cmd/spoc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"
"log"
"os"
"strings"

"github.com/urfave/cli/v2"

Expand Down Expand Up @@ -56,6 +57,18 @@ func main() {
recorder.TypeRawSeccomp,
),
},
&cli.StringSliceFlag{
Name: recorder.FlagBaseSyscalls,
Aliases: []string{"b"},
Usage: "base syscalls to be included in every profile " +
"to ensure compatibility with OCI runtimes like runc and crun",
DefaultText: strings.Join(recorder.DefaultBaseSyscalls, ", "),
},
&cli.BoolFlag{
Name: recorder.FlagNoBaseSyscalls,
Aliases: []string{"n"},
Usage: "do not add any base syscalls at all",
},
},
},
)
Expand Down
89 changes: 87 additions & 2 deletions internal/pkg/cli/recorder/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ const (

// FlagType is the flag for defining the recorder type.
FlagType string = "type"

// FlagBaseSyscalls are the syscalls included in every seccomp profile to
// ensure compatibility with OCI runtimes like runc and crun.
FlagBaseSyscalls string = "base-syscalls"

// FlagNoBaseSyscalls can be used to indicate that no base syscalls should
// be added at all.
FlagNoBaseSyscalls string = "no-base-syscalls"
)

// Type is the enum for all available recorder types.
Expand All @@ -42,5 +50,82 @@ const (
TypeRawSeccomp Type = "raw-seccomp"
)

// DefaultOutputFile defines the default output location for the recorder.
var DefaultOutputFile = filepath.Join(os.TempDir(), "profile.yaml")
var (
// DefaultOutputFile defines the default output location for the recorder.
DefaultOutputFile = filepath.Join(os.TempDir(), "profile.yaml")

// DefaultBaseSyscalls are the syscalls included in every seccomp profile
// to ensure compatibility with OCI runtimes like runc and crun.
//
// Please note that the syscalls may vary depending on which container
// runtime we choose.
DefaultBaseSyscalls = []string{
"access",
"arch_prctl",
"brk",
"capget",
"capset",
"chdir",
"close",
"close_range",
"dup2",
"dup3",
"epoll_ctl",
"epoll_pwait",
"execve",
"exit_group",
"faccessat2",
"fchdir",
"fchown",
"fcntl",
"fstat",
"fstatfs",
"futex",
"getcwd",
"getdents64",
"getegid",
"geteuid",
"getgid",
"getpid",
"getppid",
"getrandom",
"getuid",
"ioctl",
"lseek",
"mmap",
"mount",
"mprotect",
"nanosleep",
"newfstatat",
"openat",
"openat2",
"pivot_root",
"prctl",
"prlimit64",
"pselect6",
"read",
"readlink",
"rseq",
"rt_sigaction",
"rt_sigprocmask",
"rt_sigreturn",
"select",
"set_robust_list",
"set_tid_address",
"setgid",
"setgroups",
"sethostname",
"setresgid",
"setresuid",
"setsid",
"setuid",
"stat",
"statfs",
"statx",
"tgkill",
"umask",
"umount2",
"uname",
"write",
}
)
21 changes: 15 additions & 6 deletions internal/pkg/cli/recorder/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,19 @@ import (

// Options define all possible options for the recorder.
type Options struct {
typ Type
outputFile string
command string
args []string
typ Type
outputFile string
baseSyscalls []string
command string
args []string
}

// Default returns a default options instance.
func Default() *Options {
return &Options{
typ: TypeSeccomp,
outputFile: DefaultOutputFile,
typ: TypeSeccomp,
outputFile: DefaultOutputFile,
baseSyscalls: DefaultBaseSyscalls,
}
}

Expand All @@ -57,6 +59,13 @@ func FromContext(ctx *cli.Context) (*Options, error) {
return nil, fmt.Errorf("unsupported %s: %s", FlagType, options.typ)
}

if ctx.IsSet(FlagBaseSyscalls) {
options.baseSyscalls = ctx.StringSlice(FlagBaseSyscalls)
}
if ctx.IsSet(FlagNoBaseSyscalls) {
options.baseSyscalls = nil
}

args := ctx.Args().Slice()
if len(args) == 0 {
return nil, errors.New("no command provided")
Expand Down
14 changes: 14 additions & 0 deletions internal/pkg/cli/recorder/recorder.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"os/signal"
"path/filepath"
"runtime"
"sort"
"strings"
"unsafe"

Expand All @@ -40,6 +41,7 @@ import (

seccompprofileapi "sigs.k8s.io/security-profiles-operator/api/seccompprofile/v1beta1"
"sigs.k8s.io/security-profiles-operator/internal/pkg/daemon/bpfrecorder"
"sigs.k8s.io/security-profiles-operator/internal/pkg/util"
)

// Recorder is the main structure of this package.
Expand Down Expand Up @@ -143,6 +145,18 @@ func (r *Recorder) buildProfile(names []string) error {
return fmt.Errorf("get seccomp arch: %w", err)
}

if len(r.options.baseSyscalls) > 0 {
diff := []string{}
for _, syscall := range r.options.baseSyscalls {
if !util.Contains(names, syscall) {
names = append(names, syscall)
diff = append(diff, syscall)
}
}
log.Printf("Adding base syscalls: %s", strings.Join(diff, ", "))
}
sort.Strings(names)

spec := seccompprofileapi.SeccompProfileSpec{
DefaultAction: seccomp.ActErrno,
Architectures: []seccompprofileapi.Arch{arch},
Expand Down

0 comments on commit 93eed48

Please sign in to comment.