Link to this headingSECCOMP

  • Restrict a process from using specific syscalls
  • Uses BPF to interact with the kernel.

Using seccomp to limit the kernel attack surface

Link to this headinglibseccomp

Example Code:

#include <seccomp.h> #include <cstdlib> #include <iostream> int main() { std::cout << "Start: cout" << std::endl; system("echo 'Start: system'"); // SECCOMP 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

Link to this headingfirejail

Setting up the Config:

sudo firecfg firecfg --fix #Testing Profiles firejail --debug $Program > $PathToOutputFile

Run Programs:

#Run okular with default rules firejail okular #Run okular with seccomp rules firejail --seccomp okular #Run okular with custom rules firejail --profile=/absolute/path/to/profile program_name #Run with hardened malloc firejail --env=LD_PRELOAD='/usr/lib/libhardened_malloc.so' /usr/bin/firefox