Memetakan syscall-syscall berbahaya seperti mount, ptrace, process_vm_writev, kexec_load, dan userfaultfd yang sering menjadi jembatan eksploitasi kernel dan container escape. Dilengkapi tabel alasan pemblokiran, vektor serangan yang memanfaatkannya, dan contoh profile blocklist yang siap dipakai.

Di episode 12 sebelumnya kalian merangkai empat lapis pertahanan: namespaces, capabilities, seccomp, dan root read-only. Setiap lapisan sudah di tempatnya, capabilities sudah di-drop, dan filter seccomp sudah terpasang. Tetapi mari kita tarik satu langkah mundur: dari sekian ratus syscall yang bisa dipanggil sebuah proses, manakah yang seharusnya benar-benar diblokir?
Pertanyaan ini bukan akademik. Di sinilah konsep attack surface masuk ke level syscall. Bayangkan kernel Linux sebagai sebuah gedung besar dengan ratusan pintu, dan setiap pintu adalah sebuah syscall. Aplikasi kalian hanya perlu melewati segelintir pintu — membaca file, menulis output, membuka socket. Ribuan pintu lainnya tetap terpasang, terkunci atau tidak, dan setiap pintu itu adalah jalan masuk potensial bagi penyerang. Seccomp adalah keputusan tegas tentang pintu mana yang akan dikunci permanen.
Pada episode ini kita akan membedah syscall-syscall yang paling sering menjadi senjata para penyerang: mount, umount2, ptrace, process_vm_writev, kexec_load, userfaultfd, dan perf_event_open. Untuk masing-masing, kita lihat fungsi normalnya, mengapa ia berbahaya, dan vektor serangan yang memanfaatkannya — lalu merangkainya menjadi profile blocklist yang siap dipakai. Mari mulai.
Fondasi yang harus kalian pegang sejak episode awal: semua proses di Linux berbagi satu kernel. Container bukan mesin virtual — tidak ada dinding hypervisor di antara container dan host. Kernel yang sama melayani proses host dan proses di dalam container, dan bug sekecil apa pun di salah satu syscall adalah pintu masuk ke seluruh sistem.
Inilah mengapa attack surface di level syscall begitu penting. Sebuah container escape pada dasarnya berjalan seperti ini: penyerang memanfaatkan bug di handler sebuah syscall — misalnya bug use-after-free di mount atau race condition di userfaultfd — untuk mendapatkan akses memori kernel, lalu melompat keluar dari namespace container ke host. Seccomp memotong rantai ini dari hulu: jika syscall-nya diblokir, bug di handler-nya tidak akan pernah tersentuh.
Important
Ingat prinsipnya: seccomp tidak memperbaiki bug kernel — ia mencegah bug itu dipicu. Sebuah 0-day di syscall mount tidak ada artinya jika mount tidak bisa dipanggil sama sekali. Blocking attack surface adalah bentuk asuransi yang aktif bekerja bahkan sebelum kerentanan diketahui.
Berikut peta syscall yang paling sering menjadi titik masuk. Hafalkan polanya: hampir semuanya adalah syscall "power user" yang tidak pernah dibutuhkan aplikasi normal.
| Syscall | Fungsi normal | Mengapa berbahaya |
|---|---|---|
mount | Memasang filesystem | Jembatan utama container escape; dengan CAP_SYS_ADMIN bisa me-mount filesystem host |
umount2 | Melepas filesystem | Pasangan mount; bisa menanggalkan filesystem yang sedang dipakai sistem |
ptrace | Debugging antar proses | Bisa membaca dan menulis memori proses lain, termasuk proses di luar container |
process_vm_writev | Menulis memori proses lain | Menulis langsung ke address space proses lain tanpa mekanisme ptrace |
kexec_load | Memuat image kernel baru | Bisa mengganti kernel yang sedang berjalan — kontrol penuh atas host |
userfaultfd | Menangani page fault di user space | Sering dipakai untuk memenangkan race condition dan primitive eksploitasi kernel |
perf_event_open | Monitoring performance counter | Membocorkan data kernel dan pernah menjadi vektor eksploitasi informasi |
mount adalah syscall yang memasang filesystem, dan umount2 pasangannya yang melepas. Dalam container yang ideal, proses tidak pernah perlu memanggil keduanya — filesystem sudah diatur oleh runtime.
Bahayanya: dengan CAP_SYS_ADMIN (capability yang hampir selalu dibuang di episode 12), mount bisa memasang filesystem host ke dalam container. Skenario paling dikenal: me-mount /proc host ke dalam container dengan mode tulis, lalu menimpa file di host — atau me-mount filesystem host ke path yang bisa diakses, membuat seluruh sistem host terlihat. Blokir mount dan umount2 di seccomp menutup seluruh kelas serangan ini bahkan jika capability tidak sengaja lolos.
ptrace adalah syscall yang dipakai debugger seperti gdb untuk mengendalikan proses lain — membaca register, membaca dan menulis memori, menghentikan eksekusi. Jika penyerang bisa memanggil ptrace terhadap proses di luar container, ia bisa mencuri kredensial, memodifikasi logika aplikasi, atau menyuntikkan kode ke proses host.
process_vm_writev lebih licik lagi: ia menulis langsung ke address space proses lain tanpa perlu melewati mekanisme ptrace. Dengan CAP_SYS_PTRACE atau celah permission, syscall ini memberi kemampuan injeksi memori tanpa jejak debugging. Keduanya tidak pernah dibutuhkan aplikasi web atau database — blokir keduanya.
kexec_load memuat image kernel baru ke memori untuk reboot cepat. Dampaknya jika disalahgunakan sangat ekstrem: penyerang yang memegang hak yang cukup bisa mengganti kernel yang sedang berjalan dengan kernel miliknya, memberi dirinya kendali total atas host tanpa perlu escape container sama sekali.
Dari sisi defense in depth, kexec_load termasuk syscall yang hampir tidak punya alasan legal di dalam container. Blokir selalu.
userfaultfd memberi aplikasi kontrol atas penanganan page fault — proses bisa "menunda" thread lain di tengah akses memori. Ini fitur yang sah untuk checkpoint/restore dan library tertentu, tetapi menjadi momok di tangan penyerang.
Alasannya: banyak bug kernel adalah race condition — sebuah operasi memeriksa kondisi, lalu memakai datanya, dan di antara dua langkah itu ada celah. Dengan userfaultfd, penyerang bisa menghentikan thread korban tepat di celah itu, mengubah data, dan memenangkan race — pola yang sama dipakai pada serangan TOCTOU (time-of-check to time-of-use) dan sejumlah eksploitasi kernel terkenal. Memblokir userfaultfd menghilangkan primitif waktu yang paling sering dipakai penyerang.
perf_event_open membuka performance counter untuk profiling. Data yang ia hasilkan — alamat kernel, counter, sampel — dapat membocorkan informasi tentang layout memori kernel yang sangat membantu penyerang menyusun eksploitasi. Di beberapa versi kernel, syscall ini bahkan pernah menjadi vektor eksploitasi aktif.
Aplikasi produksi tidak pernah memanggil perf_event_open secara langsung. Monitoring dilakukan dari luar container (lewat agent atau node exporter), bukan dari dalam workload. Blokir syscall ini dan kalian memutus satu sumber informasi internal.
Tiga vektor utama yang memanfaatkan syscall di atas patut dirangkum karena pola pikirnya berbeda:
Kernel exploitation — penyerang memicu bug di handler syscall untuk mendapatkan arbitrary read atau arbitrary write di kernel, lalu menggunakannya untuk root di host. Sasarannya adalah syscall yang dipanggil workload. Setiap syscall yang bisa dipanggil adalah permukaan potensial; memangkas yang tidak perlu langsung memangkas kemungkinan.
Container escape — penyerang melompat dari dalam container ke host. Jembatannya hampir selalu syscall power user: mount untuk membuka filesystem host, ptrace atau process_vm_writev untuk menyentuh proses host, setns untuk masuk ke namespace host. Seccomp memblokir jembatan ini satu per satu.
Race condition — penyerang membutuhkan presisi waktu. userfaultfd adalah jam tangan paling akurat yang pernah ada untuk keperluan ini. Tanpa syscall itu, banyak eksploitasi race menjadi jauh lebih sulit, bahkan mustahil, untuk dimenangkan.
Sekarang kita rangkai menjadi profile blocklist. Karena kita hanya memblokir syscall tertentu, profile ini memakai defaultAction: SCMP_ACT_ALLOW dengan daftar deny — pola yang sama dengan profile default Docker, dan aman dipakai sebagai lapisan defense in depth.
{
"defaultAction": "SCMP_ACT_ALLOW",
"architectures": ["SCMP_ARCH_X86_64"],
"syscalls": [
{
"names": [
"mount",
"umount2",
"ptrace",
"process_vm_writev",
"kexec_load",
"userfaultfd",
"perf_event_open",
"setns"
],
"action": "SCMP_ACT_ERRNO",
"errnoRet": 1
}
]
}Kalian akan melihat setns saya tambahkan di daftar: syscall untuk berpindah namespace, dan nsenter — tool yang dipakai untuk masuk ke namespace — mengandalkannya. Ini jembatan escape lain yang layak diblokir.
Note
Profile di atas adalah deny-list, artinya ia hanya memblokir daftar ini dan mengizinkan semua syscall lain. Ini bukan policy utama yang lengkap — ia adalah lapisan dasar yang selalu aktif. Policy utama yang ketat, berbasis allow-list, adalah topik episode 17 (advanced filter design) setelah kalian menguasai observasi di episode 15.
Filter yang tidak terverifikasi hanyalah harapan. Dua pemeriksaan cepat berikut memastikan profile benar-benar terpasang dan benar-benar bekerja:
docker run --rm \
--security-opt seccomp=./profile-blocklist.json \
alpine sh -c 'grep Seccomp /proc/self/status'docker run --rm \
--security-opt seccomp=./profile-blocklist.json \
alpine sh -c 'mount -t tmpfs tmpfs /mnt; echo exit=$?'Uji kedua menunjukkan kekuatan seccomp dengan gamblang: meskipun kalian menjalankan container sebagai root, panggilan mount tetap ditolak dengan EPERM — karena gerbang syscall menolak sebelum hak apa pun dipertimbangkan. Inilah alasan deny-list di seccomp begitu berharga sebagai lapisan cadangan.
1. Menganggap blocklist sudah lengkap. Deny-list memblokir daftar yang kalian ketahui berbahaya — tidak pernah lengkap. Perlakukan sebagai lapisan tambahan, bukan pengganti allow-list.
2. Memblokir syscall yang ternyata dibutuhkan workload. Beberapa aplikasi — Java, Go, Node.js — sesekali memanggil syscall yang tidak terduga, termasuk beberapa di daftar ini dalam kondisi tertentu. Selalu uji workload di staging dengan mode LOG terlebih dahulu (episode 15) sebelum menerapkan deny.
3. Menyalin profile antar arsitektur. SCMP_ARCH_X86_64 tidak berlaku untuk host ARM64. Pastikan daftar architecture sesuai platform, atau gunakan daftar multi-arch.
4. Melupakan ptrace untuk tooling. Debugger, profiler, dan agent observability memakai ptrace dari luar. Memblokir ptrace di dalam workload tidak masalah, tetapi jangan blokir di sistem yang harus di-debug dari dalam.
Pada episode 13 ini kalian telah memetakan attack surface di level syscall. Kita membedah mengapa mount, umount2, ptrace, process_vm_writev, kexec_load, userfaultfd, dan perf_event_open menjadi sasaran favorit penyerang — dari container escape lewat mount dan setns, injeksi memori lewat ptrace dan process_vm_writev, hingga race condition yang dimenangkan dengan userfaultfd dan kebocoran informasi lewat perf_event_open. Kalian juga telah merangkainya menjadi profile blocklist dan memverifikasi bahwa filter benar-benar menolak.
Poin kunci yang perlu kalian bawa:
Ada satu pertanyaan lanjutan yang jauh lebih dalam: seberapa kuat sebenarnya filter yang kalian susun? Di episode 14 berikutnya kita akan membahas CVE awareness & security patches — tiga advisory keamanan libseccomp 2.6.1 yang dirilis Juli 2026, yang membuktikan bahwa filter yang tampak kuat bisa ternyata lemah, dan bagaimana menjaga library penyusun filter kalian selalu terkini. Sampai jumpa!