Perbandingan mendalam SECCOMP_MODE_STRICT versus SECCOMP_MODE_FILTER dari sisi keamanan, fleksibilitas, dan performa, ditambah panduan memilih return action yang tepat: KILL, TRAP, ERRNO, TRACE, ALLOW, LOG, dan NOTIFY untuk setiap skenario.

Di episode 2 kalian sudah memahami arsitektur seccomp: bagaimana filter dievaluasi di kernel, peran libseccomp, dan cara kerja mode STRICT maupun FILTER. Episode 3 ini masuk ke jantung pengambilan keputusan: apa yang dilakukan kernel ketika sebuah syscall masuk, dan apa yang harus kalian pilih saat menulis filter?
Dua hal akan kita bedah: perbandingan mendalam kedua mode operasi dari sisi keamanan dan performa, lalu seluruh return action (SECCOMP_RET_*) — apa efeknya, kapan menggunakannya, dan mengapa memilih yang tepat itu penting. Ini episode yang paling sering dirujuk ulang di sepanjang series, jadi pahami baik-baik.
Kedua mode ini menjawab era yang berbeda (episode 1) dan dipasang dengan cara berbeda (episode 2). Mari bandingkan secara sistematis:
| Aspek | SECCOMP_MODE_STRICT | SECCOMP_MODE_FILTER |
|---|---|---|
| Syscall yang diizinkan | Tetap: read, write, exit, sigreturn | Ditentukan BPF: bebas, selektif, hingga level argumen |
| Fleksibilitas | Hampir nol | Penuh: deny-list, allow-list, arg filter, multi-filter |
| Cara pemasangan | prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT) | prctl atau syscall seccomp(2) |
| Reversibel | Tidak | Tidak (praktis) |
| Overhead per syscall | Minimal (perbandingan sederhana) | Rendah; proporsional terhadap panjang filter |
| Keamanan | Sangat ketat tapi tidak praktis | Ketat dan praktis |
| Adopsi dunia nyata | Niche (honeypot, alat khusus) | Standar industri (Docker, Kubernetes, systemd) |
Dari sisi performa, keduanya sama-sama murah. Evaluasi BPF seccomp berjalan di jalur syscall paling panas, sehingga desainnya sengaja dibuat sesederhana mungkin: program BPF yang panjangnya dibatasi (maksimal 4096 instruksi), tanpa loop, dan dijamin berhenti. Overhead praktisnya berada di orde puluhan hingga ratusan nanodetik per syscall — jauh lebih kecil daripada ongkos syscall itu sendiri.
Pertimbangan keamanannya lebih menarik. Strict mode memberikan jaminan mutlak dengan cara yang brutal: hanya empat syscall, sisanya bunuh diri proses. Seccomp-bpf lebih halus: kalian memutuskan sendiri seberapa ketat, dan karena deny-list cenderung melupakan syscall berbahaya, praktik terbaik industri justru allow-list (default deny) — hanya syscall yang benar-benar dibutuhkan yang diizinkan. Kita bedah filosofi ini lebih jauh lewat return actions.
Ketika filter dievaluasi, program BPF mengembalikan sebuah return action yang menentukan nasib syscall tersebut. Kernel membandingkan nilai return action dari semua filter yang terpasang (jika berlapis) dan mengambil yang paling restriktif.
| Return Action | Nilai (hex) | Efek | Kapan Digunakan |
|---|---|---|---|
SECCOMP_RET_KILL_PROCESS | 0x80000000 | Membunuh seluruh proses (thread group) dengan SIGSYS | Syscall yang menandakan kompromi aktif, misal execve pada proses yang seharusnya tidak pernah memanggilnya |
SECCOMP_RET_KILL_THREAD | 0x00000000 | Membunuh hanya thread yang memanggil syscall | Kontrol granular per-thread; jarang dipakai di praktik modern |
SECCOMP_RET_TRAP | 0x00030000 | Mengirim SIGSYS; handler di user-space bisa menangkapnya | Ingin menangani syscall tertentu di user-space (misal untuk debugging atau emulasi) |
SECCOMP_RET_ERRNO | 0x00050000 | Syscall dibatalkan, errno dikembalikan ke aplikasi | Deny-list "lunak": aplikasi mendapat error dan tetap bisa jalan; pilihan paling umum untuk default action |
SECCOMP_RET_TRACE | 0x7ff00000 | Menyerahkan keputusan ke tracer (ptrace) | Sandbox yang disupervisi: debugger atau seccomp agent menilai syscall satu per satu |
SECCOMP_RET_ALLOW | 0x7fff0000 | Syscall diizinkan berjalan normal | Daftar syscall yang diperbolehkan dalam profil allow-list |
SECCOMP_RET_LOG | 0x7ffc0000 | Mencatat syscall ke log audit lalu mengizinkannya | Mode audit: melihat syscall apa saja yang akan diblokir sebelum benar-benar memblokirnya |
SECCOMP_RET_NOTIFY | 0x7fc00000 | Membuat syscall menunggu keputusan supervisor di user-space (kernel 5.0+) | Kebijakan dinamis: syscall kompleks seperti io_uring_setup yang butuh pertimbangan konteks |
Note
Urutan prioritas ditentukan oleh nilai numeriknya: semakin kecil nilai, semakin restriktif — dengan SECCOMP_RET_KILL_PROCESS (0x80000000) yang justru dianggap paling parah dan diberi prioritas tertinggi karena membunuh seluruh proses. Dalam praktik, cukup ingat aturan emasnya: KILL lebih kuat dari ERRNO, ERRNO lebih kuat dari ALLOW.
SECCOMP_RET_KILL_PROCESS adalah jawaban untuk "syscall apa yang tidak boleh terjadi dalam kondisi apa pun?". Jika sebuah proses yang tidak pernah memanggil execve tiba-tiba melakukannya, kemungkinan besar proses itu sedang dieksploitasi — tidak ada alasan untuk melanjutkan eksekusi. Membunuh proses adalah respons paling aman dan menghilangkan risiko berikutnya.
SECCOMP_RET_KILL_THREAD berguna ketika hanya satu thread yang melanggar dan kalian ingin thread lain tetap hidup. Praktiknya jarang — mematikan seluruh proses biasanya lebih bersih untuk keamanan — tapi penting untuk memahami perbedaannya saat membaca dokumentasi kernel.
SECCOMP_RET_ERRNO adalah pilihan default action paling umum untuk profil allow-list (seperti profile default Docker dan runc). Dengan SCMP_ACT_ERRNO(EPERM), setiap syscall yang tidak terdaftar gagal dengan "Operation not permitted" — aplikasi menerima error yang jelas, dan kalian bisa mengobservasi syscall mana yang ternyata dibutuhkan tanpa membunuh proses. Ini "mode bertahap" yang ideal untuk men-debug kebutuhan syscall aplikasi.
SECCOMP_RET_TRAP mengirim SIGSYS yang bisa ditangkap handler di user-space. Ia berguna ketika kalian ingin mengamati syscall yang diblokir sambil tetap bisa melanjutkan proses, atau ketika syscall perlu diproses secara manual. Overhead-nya lebih besar karena melibatkan sinyal, jadi bukan pilihan untuk jalur syscall yang panas.
SECCOMP_RET_TRACE menyerahkan keputusan ke tracer ptrace. Ini dipakai oleh sandbox yang terkelola: supervisor memeriksa setiap syscall dan memutuskan izin atau menolak. Konsekuensinya, proses akan bergantung pada tracer — jika tracer mati, perilaku default harus didefinisikan dengan hati-hati.
SECCOMP_RET_ALLOW adalah dasar deny-list maupun allow-list. Dalam profil allow-list, ia menjadi pengecualian yang terdaftar; dalam deny-list, ia menjadi default.
SECCOMP_RET_LOG memungkinkan kalian berlatih: syscall dicatat ke log audit tapi tetap diizinkan. Ini cara terbaik untuk memahami perilaku syscall aplikasi sebelum filter diaktifkan penuh. Kernel yang lebih lama dari 4.14 tidak mendukungnya.
SECCOMP_RET_NOTIFY (kernel 5.0+) membuat syscall menunggu sambil memberi tahu supervisor di user-space melalui notification fd. Ini adalah fitur paling modern: kebijakan bisa dinamis berdasarkan konteks aplikasi, bukan hanya statis. Kita akan bedah penuh di episode 6.
Sebagai penutup konseptual, mari kembali ke contoh praktis strict mode dari episode 2 — program sederhana yang mengaktifkan SECCOMP_MODE_STRICT:
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/prctl.h>
#include <linux/seccomp.h>
int main(void) {
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT) == -1) {
perror("prctl");
syscall(SYS_exit, 1);
}
write(STDOUT_FILENO, "strict mode aktif\n", 18);
syscall(SYS_exit, 0);
}gcc -o strict-mode strict_mode.c
./strict-mode
strict mode aktifCaution
Coba modifikasi program di atas: ganti syscall(SYS_exit, 0) dengan return 0 dan kompilasi ulang. Kalian akan melihat proses mati diam-diam tanpa output tambahan — karena exit_group tidak diizinkan strict mode. Ini pengingat terbaik mengapa dunia modern meninggalkan strict mode dan beralih ke filter yang lebih ekspresif.
Di episode 3 ini kalian sudah menguasai keputusan inti seccomp:
KILL_PROCESS, KILL_THREAD, TRAP, ERRNO, TRACE, ALLOW, LOG, dan NOTIFY.SCMP_ACT_ALLOW untuk deny-list, SCMP_ACT_ERRNO untuk allow-list), lalu aturan-aturannya.Sekarang kalian sudah punya bahasa dan konsep untuk memahami filter apa pun. Di episode 4 berikutnya kita akan berlatih sungguhan: libseccomp API dasar — seccomp_init, seccomp_rule_add, seccomp_load, seccomp_reset, dan seccomp_export_bpf, lengkap dengan contoh filter C pertama yang memblokir execve. Sampai jumpa!