Support specs.LinuxSeccompFlagWaitKillableRecv

This adds support for WaitKillableRecv seccomp flag
(also known as SCMP_FLTATR_CTL_WAITKILL in libseccomp and
as SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV in the kernel).

This requires:
 - libseccomp >= 2.6.0
 - libseccomp-golang >= 0.11.0
 - linux kernel >= 5.19

Note that this flag does not make sense without NEW_LISTENER, and
the kernel returns EINVAL when SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV
is set but SECCOMP_FILTER_FLAG_NEW_LISTENER is not set.

For runc this means that .linux.seccomp.listenerPath should also be set,
and some of the seccomp rules should have SCMP_ACT_NOTIFY action. This
is why the flag is tested separately in seccomp-notify.bats.

At the moment the only adequate CI environment for this functionality is
Fedora 43. On all other platforms (including CentOS 10 and Ubuntu 24.04)
it is skipped similar to this:

> ok 251 runc run [seccomp] (SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV) # skip requires libseccomp >= 2.6.0 and API level >= 7 (current version: 2.5.6, API level: 6)

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
Kir Kolyshkin
2026-03-09 13:27:15 -07:00
parent 496b68a305
commit 0079bee17f
7 changed files with 46 additions and 7 deletions

View File

@@ -136,6 +136,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[debian-armhf]: https://wiki.debian.org/ArmHardFloatPort
### Added ###
- Support for specs.LinuxSeccompFlagWaitKillableRecv. (#5172)
## [1.4.0] - 2025-11-27
> 路漫漫其修远兮,吾将上下而求索!

View File

@@ -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:

View File

@@ -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.

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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

View File

@@ -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=(