Hi Kees, On Tue, Jan 28, 2025 at 5:41 PM Kees Cook <kees@xxxxxxxxxx> wrote: > [...] > Also please add a KUnit tests to cover this in > tools/testing/selftests/seccomp/seccomp_bpf.c > With at least these cases combinations below. Check each of: > > - not using uretprobe passes > - using uretprobe passes (and validates that uretprobe did work) > > in each of the following conditions: > > - default-allow filter > - default-block filter > - filter explicitly blocking __NR_uretprobe and nothing else > - filter explicitly allowing __NR_uretprobe (and only other > required syscalls) In order to validate my understanding of the required test cases, I've attached a small bash script which validates them. As expected, the script fails without the suggested change. If there are gaps in my understanding of the required scope, please let me know. I plan to port these test cases to use the kselftests infrastructure as requested. To my understanding, the other issues with regards to the proposed patch are resolved, i.e. there aren't plans to support a 32 bit or mips flavor of this syscall, and the suggested patch fails closed if they are added. As such, is it possible to merge the suggested patch so it could be back merged? I'm suggesting this in the interest of time, as for example Ubuntu LTS is going to be using kernel 6.11 soon [1] and other distributions are probably going to as well, and I believe the coding/review process for the testing code will take a while and probably won't be backmerged anyway. Thanks! Eyal. [1] https://www.omgubuntu.co.uk/2025/01/ubuntu-24-04-2-release-date
#!/bin/bash -e bt=/usr/bin/bpftrace default_allow_filter=$(cat << EOF { scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_ALLOW); seccomp_load(ctx); seccomp_release(ctx); } EOF ) default_block_filter=$(cat << EOF { scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_KILL); for (int i = 0; i < num_syscalls; i++) { seccomp_rule_add(ctx, SCMP_ACT_ALLOW, seccomp_syscall_resolve_name(syscalls[i]), 0); } seccomp_load(ctx); seccomp_release(ctx); } EOF ) allow_uretprobe_filter=$(cat << EOF { scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_KILL); for (int i = 0; i < num_syscalls; i++) { seccomp_rule_add(ctx, SCMP_ACT_ALLOW, seccomp_syscall_resolve_name(syscalls[i]), 0); } seccomp_rule_add(ctx, SCMP_ACT_ALLOW, 335, 0); seccomp_load(ctx); seccomp_release(ctx); } EOF ) block_uretprobe_filter=$(cat << EOF { scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_ALLOW); seccomp_rule_add(ctx, SCMP_ACT_KILL, 335, 0); seccomp_load(ctx); seccomp_release(ctx); } EOF ) t() { with_uretprobe=$1; filter_name=$2; filter=${!filter_name}; echo "Test: uretprobe $with_uretprobe, filter $filter_name" cat > /tmp/x.c << EOF #include <stdio.h> #include <seccomp.h> char *syscalls[] = { "exit_group", }; __attribute__((noinline)) int probed(void) { return 1; } void apply_seccomp_filter(char **syscalls, int num_syscalls) $filter int main(int argc, char *argv[]) { int num_syscalls = sizeof(syscalls) / sizeof(syscalls[0]); apply_seccomp_filter(syscalls, num_syscalls); probed(); return 0; } EOF cat > /tmp/trace.bt << EOF uretprobe:/tmp/x:probed { printf("ret=%d\n", retval); } EOF gcc -o /tmp/x /tmp/x.c -lseccomp $with_uretprobe && { $bt /tmp/trace.bt & btpid=$! sleep 5 # wait for uretprobe attach } /tmp/x $with_uretprobe && kill $btpid rm /tmp/x /tmp/x.c /tmp/trace.bt } t false "default_allow_filter" t true "default_allow_filter" t false "default_block_filter" t true "default_block_filter" t false "allow_uretprobe_filter" t true "allow_uretprobe_filter" t false "block_uretprobe_filter" t true "block_uretprobe_filter"