Use bpf programs as filters for seccomp, the one in the example will block all the write syscalls after it's loaded.
Compile it with just
gcc main.c
Make sure your kernel has the right configs
cat /proc/config.gz| zcat | grep -i CONFIG_SECCOMP
CONFIG_SECCOMP=y
CONFIG_SECCOMP_FILTER=y
The program will only print the first "hey there!" then will exit
./a.out
hey there!
You can see what happens by running the program with strace
execve("./a.out", ["./a.out"], 0x7ffd85555100 /* 64 vars */) = 0
brk(NULL) = 0x5589eceec000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffe3fd63610) = -1 EINVAL (Invalid argument)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=231787, ...}) = 0
mmap(NULL, 231787, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f664b7b2000
close(3) = 0
openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000C\2\0\0\0\0\0"..., 832) = 832
lseek(3, 792, SEEK_SET) = 792
read(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\201\336\t\36\251c\324\233E\371SoK\5H\334"..., 68) = 68
fstat(3, {st_mode=S_IFREG|0755, st_size=2136840, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f664b7b0000
lseek(3, 792, SEEK_SET) = 792
read(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\201\336\t\36\251c\324\233E\371SoK\5H\334"..., 68) = 68
lseek(3, 864, SEEK_SET) = 864
read(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32) = 32
mmap(NULL, 1848896, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f664b5ec000
mprotect(0x7f664b60e000, 1671168, PROT_NONE) = 0
mmap(0x7f664b60e000, 1355776, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x22000) = 0x7f664b60e000
mmap(0x7f664b759000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16d000) = 0x7f664b759000
mmap(0x7f664b7a6000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b9000) = 0x7f664b7a6000
mmap(0x7f664b7ac000, 13888, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f664b7ac000
close(3) = 0
arch_prctl(ARCH_SET_FS, 0x7f664b7b1500) = 0
mprotect(0x7f664b7a6000, 16384, PROT_READ) = 0
mprotect(0x5589eba07000, 4096, PROT_READ) = 0
mprotect(0x7f664b814000, 4096, PROT_READ) = 0
munmap(0x7f664b7b2000, 231787) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
brk(NULL) = 0x5589eceec000
brk(0x5589ecf0d000) = 0x5589ecf0d000
write(1, "hey there!\n", 11hey there!
) = 11
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) = 0
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, {len=6, filter=0x7ffe3fd635b0}) = 0
write(1, "something's gonna happen!!\n", 27) = -1 EPERM (Operation not permitted)
write(1, "it will not definitely print thi"..., 39) = -1 EPERM (Operation not permitted)
exit_group(0) = ?
+++ exited with 0 +++
You will notice that it is giving the error code we set EPERM
when trying to do a write