From 8b58554a022b042ac499f67a275adec1a89ae7dd Mon Sep 17 00:00:00 2001 From: Ricardo Branco Date: Mon, 12 Oct 2026 12:05:06 +0200 Subject: [PATCH] seccomp: document 64-bit argument comparisons and fix masked-equal doc The kernel's seccomp filter compares the raw 64-bit argument registers, while syscalls with 32-bit argument types (e.g. the socket(2) domain) ignore the upper 32 bits. A condition such as MakeCondition(0, CompareEqual, unix.AF_NETLINK) is therefore bypassed by socket(0x100000000|AF_NETLINK, ...). Document this in MakeCondition and CompareEqual, and recommend CompareMaskedEqual with a 0xffffffff mask for 32-bit arguments. Also fix the MakeCondition comment on masked equals, which had the operand order reversed: the first value is the mask and the second is the datum. Signed-off-by: Ricardo Branco --- seccomp.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/seccomp.go b/seccomp.go index 63aabc4..42b3ed0 100644 --- a/seccomp.go +++ b/seccomp.go @@ -240,7 +240,10 @@ const ( // CompareLessOrEqual returns true if the argument is less than or equal // to the given value CompareLessOrEqual - // CompareEqual returns true if the argument is equal to the given value + // CompareEqual returns true if the argument is equal to the given value. + // Note that the comparison is done on the full 64-bit argument, while + // the kernel ignores the upper 32 bits of 32-bit arguments; see + // [MakeCondition] and https://github.com/seccomp/libseccomp/pull/504. CompareEqual // CompareGreaterEqual returns true if the argument is greater than or // equal to the given value @@ -563,11 +566,23 @@ func GetSyscallFromNameByArch(name string, arch ScmpArch) (ScmpSyscall, error) { // The rule will match if argument $arg (zero-indexed) of the syscall is // $COMPARE_OP the provided comparison value. // Some comparison operators accept two values. Masked equals, for example, -// will mask $arg of the syscall with the second value provided (via bitwise -// AND) and then compare against the first value provided. +// will mask $arg of the syscall with the first value provided (via bitwise +// AND) and then compare against the second value provided. // For example, in the less than or equal case, if the syscall argument was // 0 and the value provided was 1, the condition would match, as 0 is less // than or equal to 1. +// +// Note that the comparison is done against the full 64-bit syscall argument. +// Many syscall arguments are 32-bit types (for example, the domain argument of +// socket(2)) for which the kernel ignores the upper 32 bits, but a caller can +// set them to arbitrary values. A condition such as +// MakeCondition(0, CompareEqual, unix.AF_NETLINK) will not match a call to +// socket(2) with domain 0x100000000|AF_NETLINK, which the kernel treats the +// same as AF_NETLINK, so a rule relying on it can be bypassed. For such +// arguments use [CompareMaskedEqual] with a mask of 0xffffffff instead, for +// example MakeCondition(0, CompareMaskedEqual, 0xffffffff, unix.AF_NETLINK). +// See also https://github.com/seccomp/libseccomp/pull/504. +// // Return either an error on bad argument or a valid ScmpCondition struct. func MakeCondition(arg uint, comparison ScmpCompareOp, values ...uint64) (ScmpCondition, error) { var condStruct ScmpCondition