Repository navigation
BUG: load the syscall number in the first syscall that is emitted - #500
Open
saschagrunert wants to merge 1 commit into
Open
saschagrunert wants to merge 1 commit into
saschagrunert wants to merge 1 commit into
Conversation
_gen_bpf_syscalls() emits the instruction that loads the syscall number only in the block of the head of the sorted syscall list, but the loop omits the head when _skip_syscall() says so: an entry that only carries a priority, which seccomp_syscall_priority() leaves for a syscall without a rule, and since ad873bd ("bpf: do not add pseudo-syscalls to the BPF filter", v2.5.0) a pseudo-syscall. No block loads the number then, every rule of that architecture compares against whatever the accumulator holds after the architecture check, and every call gets the default action. The head-only load dates from 90882e7 ("bpf: fix a problem when creating filters that include syscall arguments", v2.0.0). This takes a filter whose first syscall by priority is such an entry, on an architecture whose syscall blocks load the number, which is every one but a lone x86_64 or x32. A pseudo-syscall heads the list when every unconditional rule names a syscall the architecture lacks, which the architectures with socketcall multiplexing avoid by dropping such a rule in seccomp_rule_add; a priority-only entry heads it on any architecture. With a permissive default action every denying rule of the architecture is disabled. The PFC export shows the rules as intended, so it cannot be used to find the problem. Reproducer on x86_64 with 2.5.5, 2.6.1 and main: ctx = seccomp_init(SCMP_ACT_ALLOW); seccomp_arch_add(ctx, SCMP_ARCH_X32); seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(socket), 1, SCMP_A0(SCMP_CMP_EQ, AF_VSOCK)); seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(socketcall), 0); seccomp_load(ctx); socket(AF_VSOCK, SOCK_STREAM, 0); /* succeeds, expected EPERM */ The exported BPF has no "ld [0]" after the x86_64 architecture check; without SCMP_ARCH_X32 the call fails with EPERM. The same happens with seccomp_syscall_priority(ctx, SCMP_SYS(getpid), 255) in place of the socketcall rule, on every architecture. Load the number in the first syscall that is not skipped instead of in the head. The new tests 65-sim-pseudo_syscall_first and 66-sim-priority_only_first fail without the change and pass with it; the rest of the suite still passes. Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
saschagrunert
force-pushed
the
bpf-load-syscall-first-emitted
branch
from
October 1, 2026 12:32
29e7b2f to
a04b816
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
_gen_bpf_syscalls()emits the load of the syscall number only in the block of the head of the sorted syscall list, but the loop omits the head when_skip_syscall()says so: an entry that only carries a priority, whichseccomp_syscall_priority()leaves for a syscall without a rule, and since v2.5.0 (ad873bd) a pseudo-syscall. No block loads the number then, every rule of that architecture compares against whatever the accumulator holds, and every call gets the default action. The head-only load dates from v2.0.0 (90882e7).This takes a filter whose first syscall by priority is such an entry, on an architecture whose syscall blocks load the number (all but a lone x86_64 or x32). A pseudo-syscall heads the list when every unconditional rule names a syscall the architecture lacks, which the socketcall-multiplexing architectures avoid by dropping such a rule in
seccomp_rule_add; a priority-only entry heads it on any architecture. Container runtimes load such filters from user configuration. The PFC export shows the rules as intended, so it cannot be used to find the problem. Reproducer on x86_64 with 2.5.5, 2.6.1 and main:The exported BPF has no
ld [0]after the x86_64 architecture check; withoutSCMP_ARCH_X32the call fails with EPERM. The same happens withseccomp_syscall_priority(ctx, SCMP_SYS(getpid), 255)in place of thesocketcallrule, on every architecture.The fix loads the number in the first syscall that is not skipped. The new tests
65-sim-pseudo_syscall_first(x86_64 with x32, aarch64) and66-sim-priority_only_first(x86, aarch64) fail without it and pass with it;make checkpasses.