/* This example is a bit sophisticated, because I'm showing a way how to set up a white-list using metaprogramming capabilities from Jai. For generating a white-list of syscalls you can use my tool in `tools/seccomp_collect_syscalls.py`. This records via `strace` syscalls and prints a ready to use array you can copy/paste here. Sometimes you want to only restrict syscalls from a specific point, in that case the same tool looks after a specific marker and only after that it will record syscalls. You can just print this marker in any place of your program: log("---- SECCOMP BOUNDARY ----"); Look at `sec_seccomp_init()` how to set this up. */ run :: () { log("Seccomp pre init. Writing to a FD is allowed!"); sec_seccomp_init(); log("Seccomp post init. Writing to a FD is NOT allowed!"); log("If you can read this, something went wrong!"); } #scope_file SECCOMP_ARMED :: true; /** Copy pasta from seccomp_collect_syscalls.py */ SECCOMP_ALLOWED_SYSCALLS :: string.[ "READ", "PREAD64", "SET_ROBUST_LIST", "BRK", "RT_SIGACTION", "RSEQ", "ACCESS", //! "WRITE", /** Disallow writing to a FD so we can test it! */ "ARCH_PRCTL", "PRLIMIT64", "READLINKAT", "CLOSE", "SECCOMP", "SET_TID_ADDRESS", "FSTAT", "PRCTL", "FUTEX", "GETRANDOM", "MUNMAP", "NEWFSTATAT", "MMAP", "OPENAT", "MPROTECT", "EXECVE", ]; sec_seccomp_init :: () { SECCOMP_TEMPLATE :: "had_error |= seccomp_rule_add(ctx, .ALLOW, .%);\n"; #if SECCOMP_ARMED { /** Tell seccomp what to do if a violation happened. */ ctx := seccomp_init(.KILL_PROCESS); } else { /** For development, you can just log violations. You can view them here: ausearch -m SECCOMP */ ctx := seccomp_init(.LOG); } defer seccomp_release(ctx); if !ctx { log_error("Init failed"); exit(1); } had_error := false; /** This generates the `seccomp_rule_add()` functions based of the white-list. */ #insert -> string { buf: String_Builder; for SECCOMP_ALLOWED_SYSCALLS { template := tprint(SECCOMP_TEMPLATE, it); append(*buf, template); } s := builder_to_string(*buf); return s; } /** You can also add rules here. */ had_error |= seccomp_rule_add(ctx, .ALLOW, .EXIT); had_error |= seccomp_rule_add(ctx, .ALLOW, .EXIT_GROUP); if had_error { log_error("Could not add rules."); exit(1); } if seccomp_load(ctx) < 0 { log_error("Could not load context into kernel"); exit(1); } #if SECCOMP_ARMED then log("Seccomp is armed."); else log("Seccomp is in log mode! NOT ARMED!"); /** After this point every syscall not in the white-list is blocked. */ } #import "Basic"; #import,file "../0x2_Seccomp.jai";