On Fri, Aug 08, 2025 at 01:46:13AM +0800, Wake Liu wrote: > This commit introduces checks for kernel version and seccomp filter flag > support to the seccomp selftests. It also includes conditional header > inclusions using __GLIBC_PREREQ. > > Some tests were gated by kernel version, and adjustments were made for > flags introduced after kernel 5.4. This ensures the selftests can run > and pass correctly on kernel versions 5.4 and later, preventing failures > due to features not present in older kernels. > > The use of __GLIBC_PREREQ ensures proper compilation and functionality > across different glibc versions in a mainline Linux kernel context. > While it might appear redundant in specific build environments due to > global overrides, it is crucial for upstream correctness and portability. > > Signed-off-by: Wake Liu <wa...@google.com> > --- > tools/testing/selftests/seccomp/seccomp_bpf.c | 108 ++++++++++++++++-- > 1 file changed, 99 insertions(+), 9 deletions(-) > > diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c > b/tools/testing/selftests/seccomp/seccomp_bpf.c > index 61acbd45ffaa..9b660cff5a4a 100644 > --- a/tools/testing/selftests/seccomp/seccomp_bpf.c > +++ b/tools/testing/selftests/seccomp/seccomp_bpf.c > @@ -13,12 +13,14 @@ > * we need to use the kernel's siginfo.h file and trick glibc > * into accepting it. > */ > +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) > #if !__GLIBC_PREREQ(2, 26) > # include <asm/siginfo.h> > # define __have_siginfo_t 1 > # define __have_sigval_t 1 > # define __have_sigevent_t 1 > #endif > +#endif > > #include <errno.h> > #include <linux/filter.h> > @@ -300,6 +302,26 @@ int seccomp(unsigned int op, unsigned int flags, void > *args) > } > #endif > > +int seccomp_flag_supported(int flag) > +{ > + /* > + * Probes if a seccomp filter flag is supported by the kernel. > + * > + * When an unsupported flag is passed to > seccomp(SECCOMP_SET_MODE_FILTER, ...), > + * the kernel returns EINVAL. > + * > + * When a supported flag is passed, the kernel proceeds to validate the > + * filter program pointer. By passing NULL for the filter program, > + * the kernel attempts to dereference a bad address, resulting in > EFAULT. > + * > + * Therefore, checking for EFAULT indicates that the flag itself was > + * recognized and supported by the kernel. > + */ > + if (seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL) == -1 && errno == > EFAULT) > + return 1; > + return 0; > +}
I like this! > + > #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ > #define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n])) > #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ > @@ -2436,13 +2458,12 @@ TEST(detect_seccomp_filter_flags) > ASSERT_NE(ENOSYS, errno) { > TH_LOG("Kernel does not support seccomp syscall!"); > } > - EXPECT_EQ(-1, ret); > - EXPECT_EQ(EFAULT, errno) { > - TH_LOG("Failed to detect that a known-good filter flag > (0x%X) is supported!", > - flag); > - } > > - all_flags |= flag; > + if (seccomp_flag_supported(flag)) > + all_flags |= flag; > + else > + TH_LOG("Filter flag (0x%X) is not found to be > supported!", > + flag); So I've pushed back on "backward compatible" changes to this selftest because I want it to be validating the _latest_ seccomp. This allows for expected flags to be missing. Is there perhaps a way that the backward compat checking could be a commandline flag or something? That way by default it looks strictly the more current seccomp features. -Kees -- Kees Cook