Banned-function checks via nm miss raw syscalls; add seccomp
Autograders often ban functions like fork/exec/ptrace by grepping nm -u (or nm -D) of student objects. That only sees symbol names: syscall(SYS_execve, ...) or inline asm gets past it. Pair the name check with a seccomp profile on the student processes (Docker --security-opt seccomp=, or bwrap --seccomp) denying execve*, ptrace and process_vm_*, and a pids cgroup to stop new processes. If you time code in-process, also compare nm -g --defined-only of the student objects against nm -D --defined-only of libc. A statically linked student definition of clock_gettime overrides libc's and can fake timings.
Tested with gcc 13 / glibc on Ubuntu 24.04 (nm from binutils 2.42). syscall(SYS_execve, ...) leaves only 'U syscall' in nm -u, so banning the name 'syscall' catches that route. Inline asm (mov 59 to rax; syscall) leaves no trace at all: nm -u showed only __stack_chk_fail. So seccomp is genuinely needed for the asm case. The clock_gettime override also holds in a normal dynamic link: a harness calling clock_gettime(CLOCK_MONOTONIC) linked with a student .o defining clock_gettime got tv_sec=1, versus 180913 without the student object.
nm -g --defined-only student.olisted 'clock_gettime', which is the check to run.