\$\begingroup\$

Any program executing under Linux/x86(-64)

This program is written in C, but it can disrupt execution of any program running under Linux/x86 (-32 or -64). You prepend it to the command-line invocation of the program you want to disrupt.

It uses the debugger API to prevent the target program from producing any output. Specifically, all of the system calls that can communicate something to the world outside the process (most obviously write , of course, but also open when creating a file, the bulk of the socket API, kill when applied to another process, ...) will fail as if they were unimplemented. _exit is allowed, but the exit code is overwritten with a zero.

Unlike the previous edition of this answer, many programs can run nearly to completion under these conditions; it's just that all their work is wasted. For instance, if you do ./no-syscalls /bin/ls (assuming GNU coreutils ls ) it reads the whole directory and formats it, and then all the write calls to produce output fail. (Anything that needs to open a bidirectional communication channel, though, such as all X11 clients, will fail at that point. I thought about allowing socket but not send , but it seemed too likely to open loopholes.)

There are several command-line options to tweak the behavior;

-a log allowed system calls -d log denied system calls -e deny everything, not just output -S permit writes to stderr

Dynamically linked programs will not even get out of the dynamic linker in -e mode. -S obviously opens a huge hole in the policy, but it can be entertaining to watch programs moan about nothing working, e.g.

$ ./no-syscalls -daeS /bin/ls syscall 59... syscall 59 = 0 syscall 12 (denied) = -38 syscall 21 (denied) = -38 syscall 9 (denied) = -38 syscall 20... /bin/ls: error while loading shared libraries: cannot create cache for search path: Cannot allocate memory syscall 20 = 107 syscall 231... Program exited, status = 0

You have to read log output with /usr/include/asm*/unistd.h open in another window, because this is already quite long enough.

Sadly, the debugger interfaces that this uses are only weakly consistent across Unix implementations, and are intrinsically CPU-specific. It would be relatively straightforward to port it to other CPU architectures (just add appropriate definitions of SYSCALL_*_REG ), and it's probably possible to port it to any Unix that has ptrace , but you might need to muck with the syscall whitelist extensively as well as dealing with divergences in ptrace .