diff --git a/CHANGELOG.md b/CHANGELOG.md index 4da194496a9..11c49786ced 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added ### +- Support for specs.LinuxSeccompFlagWaitKillableRecv. (#5183, #5172) + ## [1.5.0-rc.1] - 2026-03-12 > 憎しみを束ねてもそれは脆い! diff --git a/docs/spec-conformance.md b/docs/spec-conformance.md index cf79ba680e2..294adfee468 100644 --- a/docs/spec-conformance.md +++ b/docs/spec-conformance.md @@ -3,12 +3,6 @@ This branch of runc implements the [OCI Runtime Spec v1.3.0](https://github.com/opencontainers/runtime-spec/tree/v1.3.0) for the `linux` platform. -The following features are not implemented yet: - -Spec version | Feature | PR --------------|------------------------------------------------|---------------------------------------------------------- -v1.1.0 | `SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV` | [#3862](https://github.com/opencontainers/runc/pull/3862) - ## Architectures The following architectures are supported: diff --git a/libcontainer/seccomp/config.go b/libcontainer/seccomp/config.go index 476f51d5887..5c08b4ef626 100644 --- a/libcontainer/seccomp/config.go +++ b/libcontainer/seccomp/config.go @@ -109,6 +109,7 @@ var flags = []string{ flagTsync, string(specs.LinuxSeccompFlagSpecAllow), string(specs.LinuxSeccompFlagLog), + string(specs.LinuxSeccompFlagWaitKillableRecv), } // KnownFlags returns the list of the known filter flags. diff --git a/libcontainer/seccomp/patchbpf/enosys_linux.go b/libcontainer/seccomp/patchbpf/enosys_linux.go index 035d0c0d834..b9a0be8c8f8 100644 --- a/libcontainer/seccomp/patchbpf/enosys_linux.go +++ b/libcontainer/seccomp/patchbpf/enosys_linux.go @@ -51,6 +51,11 @@ const uintptr_t C_FILTER_FLAG_SPEC_ALLOW = SECCOMP_FILTER_FLAG_SPEC_ALLOW; #endif const uintptr_t C_FILTER_FLAG_NEW_LISTENER = SECCOMP_FILTER_FLAG_NEW_LISTENER; +#ifndef SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV +# define SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV (1UL << 5) +#endif +const uintptr_t C_FILTER_FLAG_WAIT_KILLABLE_RECV = SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV; + #ifndef AUDIT_ARCH_RISCV64 #ifndef EM_RISCV #define EM_RISCV 243 @@ -667,6 +672,13 @@ func filterFlags(config *configs.Seccomp, filter *libseccomp.ScmpFilter) (flags flags |= uint(C.C_FILTER_FLAG_SPEC_ALLOW) } } + if apiLevel >= 7 { + if waitKill, err := filter.GetWaitKill(); err != nil { + return 0, false, fmt.Errorf("unable to fetch SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV bit: %w", err) + } else if waitKill { + flags |= uint(C.C_FILTER_FLAG_WAIT_KILLABLE_RECV) + } + } // XXX: add newly supported filter flags above this line. for _, call := range config.Syscalls { diff --git a/libcontainer/seccomp/seccomp_linux.go b/libcontainer/seccomp/seccomp_linux.go index e399972aa53..7b3805b50b6 100644 --- a/libcontainer/seccomp/seccomp_linux.go +++ b/libcontainer/seccomp/seccomp_linux.go @@ -159,6 +159,11 @@ func setFlag(filter *libseccomp.ScmpFilter, flag specs.LinuxSeccompFlag) error { return fmt.Errorf("error adding SSB flag to seccomp filter: %w", err) } return nil + case specs.LinuxSeccompFlagWaitKillableRecv: + if err := filter.SetWaitKill(true); err != nil { + return fmt.Errorf("error adding WaitKill flag to seccomp filter: %w", err) + } + return nil } // NOTE when adding more flags above, do not forget to also: // - add new flags to `flags` slice in config.go; diff --git a/tests/integration/seccomp-notify.bats b/tests/integration/seccomp-notify.bats index b6992e5752a..c10b84be230 100644 --- a/tests/integration/seccomp-notify.bats +++ b/tests/integration/seccomp-notify.bats @@ -58,6 +58,27 @@ function scmp_act_notify_template() { [ "$status" -eq 0 ] } +@test "runc run [seccomp] (SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV)" { + scmp_act_notify_template "mkdir /dev/shm/foo && stat /dev/shm/foo-bar" false '"mkdir"' + update_config '.linux.seccomp.flags = [ "SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV" ]' + + runc --debug run test_busybox + if [ "$status" -ne 0 ]; then + # Older libseccomp or kernel? + if [[ "$output" == *"error adding WaitKill flag to seccomp filter: SetWaitKill requires "* ]]; then + skip "$(sed -e 's/^.*SetWaitKill //' -e 's/" func=.*$//' <<<"$output")" + fi + # Otherwise, fail. + [ "$status" -eq 0 ] + fi + # Check the numeric flags value, as printed in the debug log, is as expected. + # 32: SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV + # 8: SECCOMP_FILTER_FLAG_NEW_LISTENER + exp='"seccomp filter flags: 40"' + echo "expecting $exp" + [[ "$output" == *"$exp"* ]] +} + # Test actions not-handled by the agent work fine. noNewPrivileges FALSE. @test "runc exec [seccomp] (SCMP_ACT_NOTIFY noNewPrivileges false)" { requires root diff --git a/tests/integration/seccomp.bats b/tests/integration/seccomp.bats index b5ed47dbc6a..160ad16183a 100644 --- a/tests/integration/seccomp.bats +++ b/tests/integration/seccomp.bats @@ -102,8 +102,11 @@ function flags_value() { # Get the list of flags supported by runc/seccomp/kernel, # or "null" if no flags are supported or runc is too old. + # + # Filter out WAIT_KILLABLE_RECV as it requires a listener, + # and thus tested separately in seccomp-notify.bats. mapfile -t flags < <(__runc features | jq -c '.linux.seccomp.supportedFlags' | - tr -d '[]\n' | tr ',' '\n') + tr -d '[]\n' | tr ',' '\n' | grep -v 'WAIT_KILLABLE_RECV') # This is a set of all possible flag combinations to test. declare -A TEST_CASES=(