From 2ed0d97b6e58def34684a1bffc2ab6931182f221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Thu, 30 Apr 2026 22:40:37 +0200 Subject: [PATCH 1/2] seccomp: Document socket rule scope and socketcall limitation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a comment explaining the purpose of the socket rules and noting that on 32-bit x86, socket() goes through socketcall(2) which is allowed unconditionally, so these arg filters only apply to the direct socket syscall. Signed-off-by: Paweł Gronowski --- contrib/seccomp/seccomp_default.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contrib/seccomp/seccomp_default.go b/contrib/seccomp/seccomp_default.go index b75eea0b1f..b1e954c27a 100644 --- a/contrib/seccomp/seccomp_default.go +++ b/contrib/seccomp/seccomp_default.go @@ -426,6 +426,10 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp { Action: specs.ActAllow, Args: []specs.LinuxSeccompArg{}, }, + // Allow socket(2) for all address families except AF_VSOCK. + // NOTE: on 32-bit x86, socket() goes through socketcall(2) which is + // allowed unconditionally above; these arg filters only apply to the + // direct socket syscall. { Names: []string{"socket"}, Action: specs.ActAllow, From 4d80a31bf637bc15e83e50a15941bf5bb0cb3988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= Date: Thu, 30 Apr 2026 21:31:01 +0200 Subject: [PATCH 2/2] seccomp: Block AF_ALG in default socket policy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AF_ALG (address family 38) exposes the Linux kernel crypto API to userspace via socket(2). Containers have no legitimate need for this interface under the default profile, and leaving it accessible widens the kernel attack surface unnecessarily (see https://copy.fail/). Signed-off-by: Paweł Gronowski --- contrib/seccomp/seccomp_default.go | 45 ++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/contrib/seccomp/seccomp_default.go b/contrib/seccomp/seccomp_default.go index b1e954c27a..d48983dd6c 100644 --- a/contrib/seccomp/seccomp_default.go +++ b/contrib/seccomp/seccomp_default.go @@ -426,10 +426,45 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp { Action: specs.ActAllow, Args: []specs.LinuxSeccompArg{}, }, - // Allow socket(2) for all address families except AF_VSOCK. - // NOTE: on 32-bit x86, socket() goes through socketcall(2) which is - // allowed unconditionally above; these arg filters only apply to the - // direct socket syscall. + // Allow socket(2) for all address families except AF_VSOCK and AF_ALG. + // NOTE: on socketcall(2)-based ABIs (for example 32-bit x86), socket() + // goes through socketcall(2), which is allowed unconditionally above. + // These arg filters only apply to the direct socket syscall. + // + // Do not use one rule with both "arg0 != AF_VSOCK" and "arg0 != AF_ALG". + // runc splits repeated argument-index conditions into separate + // libseccomp rules, so they behave like OR and allow both blocked + // domains. + // + // Do not combine explicit ERRNO rules with a broad socket ALLOW. + // libseccomp can make the ERRNO branch unreachable, collapse an + // unconditional ALLOW into a bare syscall allow, or silently reject + // repeated not-equal checks. + // + // These three single-condition ranges make AF_ALG and AF_VSOCK match + // none and fall through to the default errno action. + { + Names: []string{"socket"}, + Action: specs.ActAllow, + Args: []specs.LinuxSeccompArg{ + { + Index: 0, + Value: unix.AF_ALG, + Op: specs.OpLessThan, + }, + }, + }, + { + Names: []string{"socket"}, + Action: specs.ActAllow, + Args: []specs.LinuxSeccompArg{ + { + Index: 0, + Value: unix.AF_ALG + 1, + Op: specs.OpEqualTo, + }, + }, + }, { Names: []string{"socket"}, Action: specs.ActAllow, @@ -437,7 +472,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp { { Index: 0, Value: unix.AF_VSOCK, - Op: specs.OpNotEqual, + Op: specs.OpGreaterThan, }, }, },