From 57fcb5adae50df92450159aa6accde1d68c0acae Mon Sep 17 00:00:00 2001 From: ychampion Date: Sat, 11 Jul 2026 18:12:16 +0000 Subject: [PATCH] seccomp: unblock limited fanotify groups Allow the kernel to apply its post-5.13 capability restrictions instead of rejecting fanotify_init at the seccomp layer. Constraint: Unprivileged fanotify groups remain limited by the kernel API. Rejected: Gate the syscall on a minimum kernel version | older kernels already reject unprivileged callers with EPERM. Confidence: high Scope-risk: narrow Directive: Keep default.json generated from default_linux.go. Tested: Full module tests and vet; seccomp race tests; five Linux cross-builds; golangci-lint 2.12.2; stable code generation. Not-tested: End-to-end Docker daemon reproduction. Signed-off-by: ychampion --- seccomp/default.json | 2 +- seccomp/default_linux.go | 2 +- seccomp/seccomp_linux_test.go | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/seccomp/default.json b/seccomp/default.json index ea5a494..c8a8efb 100644 --- a/seccomp/default.json +++ b/seccomp/default.json @@ -110,6 +110,7 @@ "fadvise64", "fadvise64_64", "fallocate", + "fanotify_init", "fanotify_mark", "fchdir", "fchmod", @@ -635,7 +636,6 @@ "bpf", "clone", "clone3", - "fanotify_init", "fsconfig", "fsmount", "fsopen", diff --git a/seccomp/default_linux.go b/seccomp/default_linux.go index f0f8df0..30507c8 100644 --- a/seccomp/default_linux.go +++ b/seccomp/default_linux.go @@ -113,6 +113,7 @@ func DefaultProfile() *Seccomp { "fadvise64", "fadvise64_64", "fallocate", + "fanotify_init", "fanotify_mark", "fchdir", "fchmod", @@ -643,7 +644,6 @@ func DefaultProfile() *Seccomp { "bpf", "clone", "clone3", - "fanotify_init", "fsconfig", "fsmount", "fsopen", diff --git a/seccomp/seccomp_linux_test.go b/seccomp/seccomp_linux_test.go index a4282db..c1b83ca 100644 --- a/seccomp/seccomp_linux_test.go +++ b/seccomp/seccomp_linux_test.go @@ -7,6 +7,7 @@ import ( "encoding/json" "os" "reflect" + "slices" "strings" "testing" @@ -195,6 +196,24 @@ func TestLoadDefaultProfile(t *testing.T) { } } +func TestDefaultProfileAllowsFanotifyInitWithoutSysAdmin(t *testing.T) { + spec := createSpec() + profile, err := GetDefaultProfile(&spec) + if err != nil { + t.Fatal(err) + } + + for _, syscall := range profile.Syscalls { + if slices.Contains(syscall.Names, "fanotify_init") { + if syscall.Action != specs.ActAllow { + t.Fatalf("expected fanotify_init action %s, got %s", specs.ActAllow, syscall.Action) + } + return + } + } + t.Fatal("fanotify_init is not allowed without CAP_SYS_ADMIN") +} + func TestUnmarshalDefaultProfile(t *testing.T) { expected := DefaultProfile() if expected == nil {