From 6851458a96332f8b11733bde8f272f5a2128208c Mon Sep 17 00:00:00 2001 From: rawrmonster17 Date: Thu, 18 Jun 2026 22:45:15 -0500 Subject: [PATCH] arch-syscall-check: verify #ifdef __NR_ guards match __SNR_ define names The arch-syscall-check script already verifies that the set of syscall names in syscalls.csv matches the set of __SNR_ defines in seccomp-syscalls.h. However it does not verify that each '#ifdef __NR_' guard immediately preceding a '#define __SNR_' uses the same syscall name as the define it guards. A mismatch -- e.g. '#ifdef __NR_foo' guarding '#define __SNR_bar' -- means the define will silently resolve to __PNR_bar (not present) even when __NR_foo is defined by the kernel headers, rendering the syscall unreachable through libseccomp on any arch that has it. Add check_snr_ifdef() which reads seccomp-syscalls.h line by line and reports any '#ifdef __NR_' / '#define __SNR_' pairing where X and Y differ. Any other preprocessor directive between the #ifdef and the matching #define resets the pending guard name (handles the unconditional '#define __SNR_x __NR_x' form, which carries no #ifdef and needs no cross-check). The exit code from check_snr_ifdef() is accumulated into the script's overall return code alongside the existing check_snr() and check_pnr() checks, so a guard mismatch will fail the 'arch-syscall-check' test that runs as part of 'make check'. Fixes: Github Issue #315 Signed-off-by: rawrmonster17 --- src/arch-syscall-check | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/arch-syscall-check b/src/arch-syscall-check index 9c7fd419..eec6d516 100755 --- a/src/arch-syscall-check +++ b/src/arch-syscall-check @@ -50,6 +50,44 @@ function check_pnr() { [[ $? -eq 1 ]] && return 0 || return 1 } +function check_snr_ifdef() { + # Verify that each "#ifdef __NR_" guard immediately preceding a + # "#define __SNR_" uses the same syscall name as the define. + # A mismatch (e.g. "#ifdef __NR_foo" followed by "#define __SNR_bar") + # means the define will silently use the wrong guard and may resolve + # to __PNR_bar even when __NR_foo is present on the target arch. + local mismatch=0 + local ifdef_name="" + local lineno=0 + + while IFS= read -r line; do + (( lineno++ )) + + if [[ "$line" =~ ^#ifdef[[:space:]]+__NR_(.+)$ ]]; then + ifdef_name="${BASH_REMATCH[1]}" + elif [[ -n "$ifdef_name" ]]; then + if [[ "$line" =~ ^#define[[:space:]]+__SNR_([^[:space:]]+) ]]; then + snr_name="${BASH_REMATCH[1]}" + if [[ "$ifdef_name" != "$snr_name" ]]; then + echo "MISMATCH at $SYSCALL_HDR:$lineno:" \ + "#ifdef __NR_$ifdef_name" \ + "but #define __SNR_$snr_name" + mismatch=1 + fi + ifdef_name="" + elif [[ "$line" =~ ^#ifdef || "$line" =~ ^#define || \ + "$line" =~ ^#else || "$line" =~ ^#endif ]]; then + # Any other preprocessor directive clears the + # pending ifdef_name without a match being needed + # (e.g. unconditional defines have no #ifdef guard) + ifdef_name="" + fi + fi + done < "$SYSCALL_HDR" + + return $mismatch +} + rc=0 echo ">>> CHECKING FOR MISSING __SNR_syscall VALUES" @@ -60,4 +98,8 @@ echo ">>> CHECKING FOR MISSING __PNR_syscall VALUES" check_pnr rc=$(( $rc + $? )) +echo ">>> CHECKING FOR MISMATCHED __SNR_syscall/#ifdef __NR_syscall NAMES" +check_snr_ifdef +rc=$(( $rc + $? )) + exit $rc