diff --git a/libcontainer/seccomp/config.go b/libcontainer/seccomp/config.go index b54b7eead3b..2e5adfd3a52 100644 --- a/libcontainer/seccomp/config.go +++ b/libcontainer/seccomp/config.go @@ -56,9 +56,7 @@ func ConvertStringToOperator(in string) (configs.Operator, error) { } // ConvertStringToAction converts a string into a Seccomp rule match action. -// Actions use the names they are assigned in Libseccomp's header, though some -// (notable, SCMP_ACT_TRACE) are not available in this implementation and will -// return errors. +// Actions use the names they are assigned in Libseccomp's header. // Attempting to convert a string that is not a valid action results in an // error. func ConvertStringToAction(in string) (configs.Action, error) { diff --git a/libcontainer/seccomp/seccomp_linux.go b/libcontainer/seccomp/seccomp_linux.go index fbbe8219782..58cad90262b 100644 --- a/libcontainer/seccomp/seccomp_linux.go +++ b/libcontainer/seccomp/seccomp_linux.go @@ -6,11 +6,12 @@ import ( "errors" "fmt" - "github.com/opencontainers/runc/libcontainer/configs" - "github.com/opencontainers/runc/libcontainer/seccomp/patchbpf" - libseccomp "github.com/seccomp/libseccomp-golang" + "github.com/sirupsen/logrus" "golang.org/x/sys/unix" + + "github.com/opencontainers/runc/libcontainer/configs" + "github.com/opencontainers/runc/libcontainer/seccomp/patchbpf" ) var ( @@ -67,7 +68,7 @@ func InitSeccomp(config *configs.Seccomp) error { if call == nil { return errors.New("encountered nil syscall while initializing Seccomp") } - if err := matchCall(filter, call); err != nil { + if err := matchCall(filter, call, defaultAction); err != nil { return err } } @@ -142,7 +143,7 @@ func getCondition(arg *configs.Arg) (libseccomp.ScmpCondition, error) { } // Add a rule to match a single syscall -func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall) error { +func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall, defAct libseccomp.ScmpAction) error { if call == nil || filter == nil { return errors.New("cannot use nil as syscall to block") } @@ -151,17 +152,23 @@ func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall) error { return errors.New("empty string is not a valid syscall") } - // If we can't resolve the syscall, assume it's not supported on this kernel - // Ignore it, don't error out - callNum, err := libseccomp.GetSyscallFromName(call.Name) + // Convert the call's action to the libseccomp equivalent + callAct, err := getAction(call.Action, call.ErrnoRet) if err != nil { + return fmt.Errorf("action in seccomp profile is invalid: %w", err) + } + if callAct == defAct { + // This rule is redundant, silently skip it + // to avoid error from AddRule. return nil } - // Convert the call's action to the libseccomp equivalent - callAct, err := getAction(call.Action, call.ErrnoRet) + // If we can't resolve the syscall, assume it is not supported + // by this kernel. Warn about it, don't error out. + callNum, err := libseccomp.GetSyscallFromName(call.Name) if err != nil { - return fmt.Errorf("action in seccomp profile is invalid: %w", err) + logrus.Debugf("unknown seccomp syscall %q ignored", call.Name) + return nil } // Unconditional match - just add the rule diff --git a/tests/integration/start_hello.bats b/tests/integration/start_hello.bats index 858847032c3..1c3c906fa53 100644 --- a/tests/integration/start_hello.bats +++ b/tests/integration/start_hello.bats @@ -76,3 +76,15 @@ function teardown() { runc run test_hello [ "$status" -eq 0 ] } + +@test "runc run [redundant seccomp rules]" { + update_config ' .linux.seccomp = { + "defaultAction": "SCMP_ACT_ALLOW", + "syscalls": [{ + "names": ["bdflush"], + "action": "SCMP_ACT_ALLOW", + }] + }' + runc run test_hello + [ "$status" -eq 0 ] +}