Merge pull request #5564 from kolyshkin/seccomp-errnoret

libct/configs/validate: reject seccomp errnoRet for unsupported actions
This commit is contained in:
Kir Kolyshkin authored and GitHub committed 2026-11-05 07:33:02 +00:00
commit 48dfb3a2c0
4 files changed
+124

No files matched your search

+4
View File
@@ -39,6 +39,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Running a container which does not have its own mount namespace no longer
changes the propagation of host's `/` and of the parent mount of the
container rootfs (they were made private or slave). (#5537)
- runc now errors out when seccomp `defaultErrnoRet` or `errnoRet` is set for
an action which does not support it (i.e. anything other than
`SCMP_ACT_ERRNO` and `SCMP_ACT_TRACE`), as required by the runtime spec.
Previously, such values were silently ignored. (#5550, #5564)
## [1.6.0-rc.1] - 2026-10-06
@@ -32,6 +32,7 @@ func Validate(config *configs.Config) error {
rootfs,
rootlessEUIDCheck,
scheduler,
seccompCheck,
selinuxCheck,
sysctl,
uts,
@@ -543,3 +544,24 @@ func memoryPolicy(config *configs.Config) error {
}
return nil
}
func seccompCheck(config *configs.Config) error {
sc := config.Seccomp
if sc == nil {
return nil
}
// The runtime spec requires an error if errnoRet
// is set for an action that does not support it.
supportsErrno := func(a configs.Action) bool {
return a == configs.Errno || a == configs.Trace
}
if sc.DefaultErrnoRet != nil && !supportsErrno(sc.DefaultAction) {
return errors.New("seccomp: defaultErrnoRet is only supported for SCMP_ACT_ERRNO and SCMP_ACT_TRACE actions")
}
for _, call := range sc.Syscalls {
if call != nil && call.ErrnoRet != nil && !supportsErrno(call.Action) {
return fmt.Errorf("seccomp: syscall %q: errnoRet is only supported for SCMP_ACT_ERRNO and SCMP_ACT_TRACE actions", call.Name)
}
}
return nil
}
@@ -1168,3 +1168,80 @@ func TestDevValidName(t *testing.T) {
})
}
}
func TestValidateSeccompErrnoRet(t *testing.T) {
errno := uint(1)
testCases := []struct {
name string
seccomp *configs.Seccomp
isErr bool
}{
{
name: "defaultErrnoRet with SCMP_ACT_ERRNO",
seccomp: &configs.Seccomp{
DefaultAction: configs.Errno,
DefaultErrnoRet: &errno,
},
},
{
name: "defaultErrnoRet with SCMP_ACT_TRACE",
seccomp: &configs.Seccomp{
DefaultAction: configs.Trace,
DefaultErrnoRet: &errno,
},
},
{
name: "defaultErrnoRet with SCMP_ACT_ALLOW",
seccomp: &configs.Seccomp{
DefaultAction: configs.Allow,
DefaultErrnoRet: &errno,
},
isErr: true,
},
{
name: "errnoRet with SCMP_ACT_ERRNO",
seccomp: &configs.Seccomp{
DefaultAction: configs.Allow,
Syscalls: []*configs.Syscall{
{Name: "mkdir", Action: configs.Errno, ErrnoRet: &errno},
},
},
},
{
name: "errnoRet with SCMP_ACT_KILL_PROCESS",
seccomp: &configs.Seccomp{
DefaultAction: configs.Allow,
Syscalls: []*configs.Syscall{
{Name: "mkdir", Action: configs.KillProcess, ErrnoRet: &errno},
},
},
isErr: true,
},
{
name: "errnoRet with redundant SCMP_ACT_ALLOW",
seccomp: &configs.Seccomp{
DefaultAction: configs.Allow,
Syscalls: []*configs.Syscall{
{Name: "mkdir", Action: configs.Allow, ErrnoRet: &errno},
},
},
isErr: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
config := &configs.Config{
Rootfs: "/var",
Seccomp: tc.seccomp,
}
err := Validate(config)
if tc.isErr && err == nil {
t.Error("expected error, got nil")
}
if !tc.isErr && err != nil {
t.Errorf("expected nil, got error %v", err)
}
})
}
}
+21
View File
@@ -60,6 +60,27 @@ function teardown() {
assert_output --partial "Network is down"
}
@test "runc run [seccomp] (errnoRet with unsupported action)" {
update_config '.process.args = ["/bin/true"]'
# defaultErrnoRet with a default action not supporting it.
update_config '.linux.seccomp = {
"defaultAction":"SCMP_ACT_ALLOW",
"defaultErrnoRet": 1
}'
run ! runc run test_busybox
assert_output --partial "defaultErrnoRet is only supported for"
# errnoRet with a syscall action not supporting it (the rule is
# redundant as it is the same as the default action).
update_config '.linux.seccomp = {
"defaultAction":"SCMP_ACT_ALLOW",
"syscalls":[{"names":["mkdir","mkdirat"], "action":"SCMP_ACT_ALLOW", "errnoRet": 1}]
}'
run ! runc run test_busybox
assert_output --regexp 'syscall .*mkdir.*: errnoRet is only supported for'
}
# Prints the numeric value of provided seccomp flags combination.
# The parameter is flags string, as supplied in OCI spec, for example
# '"SECCOMP_FILTER_FLAG_TSYNC","SECCOMP_FILTER_FLAG_LOG"'.