- Restrict a process from using specific syscalls
- Uses BPF to interact with the kernel.
Using seccomp to limit the kernel attack surface
Example Code:
#include <seccomp.h>
#include <cstdlib>
#include <iostream>
int main() {
std::cout << "Start: cout" << std::endl;
system("echo 'Start: system'");
scmp_filter_ctx ctx;
ctx = seccomp_init(SCMP_ACT_KILL);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
seccomp_load(ctx);
std::cout << "End: cout" << std::endl;
system("echo 'End: system'");
return 0;
}
Get Seccomp rules for a binary:
>>> ~/.local/share/gem/ruby/3.3.0/bin/seccomp-tools dump ./a.out
Start: cout
Start: system
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x08 0xc000003e if (A != ARCH_X86_64) goto 0010
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x05 0xffffffff if (A != 0xffffffff) goto 0010
0005: 0x15 0x03 0x00 0x00000000 if (A == read) goto 0009
0006: 0x15 0x02 0x00 0x00000001 if (A == write) goto 0009
0007: 0x15 0x01 0x00 0x0000000f if (A == rt_sigreturn) goto 0009
0008: 0x15 0x00 0x01 0x0000003c if (A != exit) goto 0010
0009: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0010: 0x06 0x00 0x00 0x00000000 return KILL
Setting up the Config:
sudo firecfg
firecfg --fix
firejail --debug $Program > $PathToOutputFile
Run Programs:
firejail okular
firejail --seccomp okular
firejail --profile=/absolute/path/to/profile program_name
firejail --env=LD_PRELOAD='/usr/lib/libhardened_malloc.so' /usr/bin/firefox