@@ -374,7 +374,6 @@ func DefaultProfile() *Seccomp {
374374 "signalfd4" ,
375375 "sigprocmask" ,
376376 "sigreturn" ,
377- "socketcall" ,
378377 "socketpair" ,
379378 "splice" ,
380379 "stat" ,
@@ -442,12 +441,27 @@ func DefaultProfile() *Seccomp {
442441 MinKernel : & KernelVersion {4 , 8 },
443442 },
444443 },
444+ // socketcall(2) is explicitly denied to prevent bypassing the socket
445+ // address family filters above on architectures where socketcall is
446+ // supported (i386, s390, MIPS o32).
447+ // Seccomp cannot inspect socketcall's pointer argument, so allowing it
448+ // would let an attacker open AF_ALG sockets via socketcall(SYS_SOCKET,
449+ // ...). Since Linux 4.3 all affected architectures provide direct
450+ // socket syscalls, so modern userspace is not impacted.
451+ //
452+ // ENOSYS (not EPERM) is used because the errno must differ from
453+ // DefaultErrnoRet; otherwise both runc and libseccomp treat the rule
454+ // as identical to the default action and silently omit it from the
455+ // generated BPF, which lets libseccomp's auto-generated
456+ // socketcall(SYS_SOCKET) -> ALLOW path survive unchallenged.
457+ {
458+ LinuxSyscall : specs.LinuxSyscall {
459+ Names : []string {"socketcall" },
460+ Action : specs .ActErrno ,
461+ ErrnoRet : & nosys ,
462+ },
463+ },
445464 // Allow socket(2) for all address families except AF_VSOCK and AF_ALG.
446- // NOTE: on 32-bit x86, socket() goes through socketcall(2) which is
447- // allowed unconditionally above, so AF_VSOCK/AF_ALG is still reachable
448- // via the socketcall-based socket() path. These arg filters only apply
449- // to the direct socket syscall, and do not protect 32-bit x86 unless
450- // socketcall(2) is also addressed.
451465 {
452466 LinuxSyscall : specs.LinuxSyscall {
453467 Names : []string {"socket" },
0 commit comments