Filter Seccomp Mengurangi Permukaan Syscall Tanpa Membentuk Sandbox Lengkap

Sebuah layanan dapat berjalan dengan allowlist seccomp yang pendek tetapi tetap memiliki otoritas luas melalui file descriptor, izin filesystem, endpoint jaringan, dan kredensial. Filter dapat mengurangi secara tajam interface kernel yang dapat dicapai melalui syscall, tetapi proses masih mampu melakukan tindakan berbahaya melalui operasi yang memang diizinkan. Inilah batas utama seccomp: mekanisme ini memfilter percobaan syscall; mekanisme ini tidak menetapkan seluruh kebijakan keamanan sebuah proses.

Dokumentasi kernel Linux menempatkan seccomp filtering sebagai mekanisme untuk mengurangi permukaan kernel yang terekspos dan secara eksplisit membedakannya dari sandbox lengkap. Perbedaan tersebut menjadi penting secara operasional ketika deployment memperlakukan profil seccomp yang lolos sebagai bukti containment, bukan sebagai satu lapisan dalam rancangan isolasi yang lebih besar.

Filter melihat metadata syscall, bukan maksud aplikasi

Mode filter seccomp mengevaluasi program BPF terhadap struct seccomp_data. Data yang tersedia mencakup nomor syscall, identifier arsitektur, instruction pointer, dan nilai mentah argumen syscall. Filter mengembalikan action yang memberi tahu kernel untuk mengizinkan call, menolaknya, menghentikan eksekusi, memberi notifikasi ke komponen lain, atau mengambil action seccomp lain yang didukung.

Filter tidak menafsirkan maksud pada level aplikasi. Mengizinkan write() tidak membedakan penulisan log yang aman dari modifikasi melalui descriptor yang sudah terbuka. Mengizinkan sendmsg() tidak menetapkan pesan aplikasi mana yang dapat diterima. Kernel mengevaluasi nilai yang terlihat pada batas syscall, bukan makna semantik data di balik nilai tersebut.

Argumen pointer memperjelas batas itu. Classic seccomp BPF tidak melakukan dereference pointer userspace. Filter dapat memeriksa nilai numerik pointer yang diberikan sebagai argumen, tetapi tidak dapat dengan aman mengurai pathname, struktur socket, atau buffer yang ditunjuk sebagai bagian dari evaluasi filter biasa. Pembatasan ini menghindari satu kelas race time-of-check/time-of-use pada mekanisme filtering, sekaligus membatasi kebijakan yang dapat diekspresikan filter.

Kebijakan yang memerlukan otoritas berbasis pathname, label objek, atau semantik resource yang lebih kaya karena itu berada pada mekanisme enforcement lain atau susunan supervisor yang dirancang dengan cermat. Seccomp tetap berguna justru karena titik enforcement-nya sempit dan terdefinisi secara mekanis.

Pemeriksaan arsitektur adalah bagian dari identitas syscall

Nomor syscall tidak memiliki makna global tanpa calling convention. Linux dapat mendukung beberapa ABI syscall pada satu mesin, dan identifier syscall numerik dapat berbeda atau tumpang tindih di antara ABI tersebut. Input seccomp karena itu menyertakan nilai arsitektur, dan dokumentasi kernel memperingatkan agar filter memvalidasinya sebelum mengandalkan nomor syscall.

Ini bukan metadata dekoratif. Filter yang mengasumsikan satu ABI sementara proses dapat memanggil ABI lain dapat mengklasifikasikan nilai syscall numerik menggunakan tabel yang keliru. Konstruksi kebijakan yang benar mengikat pemeriksaan arsitektur dan nomor syscall sebagai satu kesatuan.

Prinsip yang sama berlaku pada interpretasi argumen. Posisi dan lebar argumen mentah merupakan properti ABI syscall. Profil yang dibuat untuk satu lingkungan eksekusi tidak semestinya dianggap sebagai kebijakan portabel hanya karena nama syscall tampak identik pada level yang lebih tinggi.

Instalasi filter memiliki batas privilege sendiri

Task tanpa privilege tidak dapat secara bebas memasang filter yang bertahan melewati execve() lalu memakai filter tersebut untuk memanipulasi program dengan privilege lebih tinggi. Linux membatasi risiko itu dengan mensyaratkan task memiliki CAP_SYS_ADMIN di user namespace-nya atau menetapkan no_new_privs sebelum memasang filter seccomp.

Setelah ditetapkan, no_new_privs diwariskan melalui fork(), clone(), dan execve() serta tidak dapat dinonaktifkan. Kontraknya pada execve() mencegah transisi tersebut memberikan privilege yang sebelumnya tidak tersedia, termasuk kenaikan privilege dari set-user-ID, set-group-ID, dan file capabilities.

Kedua mekanisme menyelesaikan persoalan yang berbeda. no_new_privs membatasi kenaikan privilege melalui transisi eksekusi. Seccomp membatasi penanganan syscall sesuai filter yang terpasang. Keduanya, jika berdiri sendiri, tidak mencabut file descriptor yang sudah dimiliki proses, mengubah kepemilikan filesystem, menghapus jangkauan jaringan, atau menyediakan kebijakan mandatory access control.

Filter tambahan dapat mempersempit kebijakan tetapi tidak melonggarkannya

Seccomp mengizinkan filter disusun berlapis. Ketika beberapa filter mengevaluasi sebuah syscall, kernel memilih action dengan precedence tertinggi, bukan membiarkan filter yang dipasang kemudian menimpa keputusan restriktif sebelumnya dengan SECCOMP_RET_ALLOW.

Sifat ini memberi filter stacking karakter keamanan monoton pada level action: penambahan filter dapat menghasilkan keputusan yang sama atau lebih restriktif untuk evaluasi syscall, tetapi tidak dapat menghapus filter terdahulu. Properti tersebut mendukung proses yang mengurangi permukaan syscall ketika berpindah dari fase inisialisasi ke fase operasi.

Konsekuensi operasionalnya adalah riwayat kebijakan tetap berpengaruh. Proses tidak dapat memasang filter restriktif sementara lalu menghapusnya ketika suatu fase berakhir. Rancangan yang memerlukan transisi kebijakan reversibel membutuhkan arsitektur lain, sering kali berupa proses terpisah dengan lifetime dan batas privilege berbeda.

Filter stacking juga membawa biaya evaluasi. Dokumentasi kernel mencatat bahwa filter tambahan meningkatkan waktu evaluasi. Kebijakan yang sangat besar atau berlapis berulang kali karena itu memiliki pertimbangan performa di samping efek keamanannya.

Proses multithread membuat waktu instalasi terlihat

Proses multithread dapat berada dalam kondisi tidak konsisten jika hanya satu thread memasuki rezim filter baru sementara sibling tetap memakai set yang lebih lama. Flag SECCOMP_FILTER_FLAG_TSYNC tersedia untuk menyinkronkan filter ke thread lain dalam proses pemanggil ketika kernel dapat melakukannya.

Sinkronisasi dapat gagal jika sibling berada dalam state yang menghalangi transisi tersebut, misalnya memiliki ancestry filter seccomp yang tidak dapat diselaraskan dengan filter tree milik pemanggil. Deployment karena itu perlu memperlakukan keberhasilan instalasi filter sebagai hasil yang harus diperiksa, bukan asumsi setelah call dicoba.

Waktu sebelum sinkronisasi juga relevan. Thread yang dibuat sebelum confinement dapat mengeksekusi kode dalam jendela ketika filter yang dimaksud belum aktif. Memasang kebijakan sebelum menerima input tidak tepercaya atau memulai concurrency yang tidak diperlukan mengurangi jumlah state transisi yang harus dipercaya.

Return action mengubah perilaku kegagalan, bukan otoritas resource

Kebijakan seccomp dapat menolak syscall dengan SECCOMP_RET_ERRNO, menghentikan thread atau proses, menghasilkan SIGSYS melalui SECCOMP_RET_TRAP, melakukan logging sambil tetap mengizinkan eksekusi, atau memakai action lain yang didukung kernel yang sedang berjalan. Pilihan ini membentuk observability dan semantik kegagalan.

SECCOMP_RET_ERRNO dapat membuat call yang ditolak tampak seperti kegagalan kernel biasa bagi kode aplikasi. Action terminasi membuat pelanggaran kebijakan gagal tertutup dengan biaya pada availability proses. SECCOMP_RET_LOG menjalankan syscall setelah mencatatnya, sehingga action ini merupakan mekanisme observasi, bukan batas penolakan.

SECCOMP_RET_USER_NOTIF menambahkan arsitektur berbeda. Call tertentu dapat dikirim ke supervisor userspace melalui listener file descriptor. Supervisor dapat merespons notifikasi dan, melalui operasi yang didukung, memasukkan file descriptor ke target. Pola ini berguna untuk container manager dan sistem mediasi sejenis, tetapi memindahkan sebagian keputusan ke protokol userspace yang concurrent.

Model supervisor tidak membuat pemeriksaan pointer menjadi operasi kebijakan yang sederhana. Jika supervisor membaca memori target untuk menafsirkan argumen pointer, memori tersebut dapat berubah secara concurrent kecuali rancangan menangani race itu. Dokumentasi kernel secara eksplisit memperingatkan risiko time-of-check/time-of-use pada jalur ini.

Syscall yang diizinkan masih dapat memakai otoritas yang kuat

Set syscall yang sempit dapat tetap sangat mampu. Proses yang sudah memegang descriptor writable dapat mengubah objek yang dirujuk melalui call I/O biasa. Socket yang sudah terhubung dapat membawa perintah ke peer dengan privilege tinggi. Memory mapping dapat mengekspos state bersama. Descriptor warisan dapat melewati batas execve() kecuali flag descriptor dan kebijakan peluncuran proses menutupnya.

Seccomp tidak menempelkan izin khusus resource pada objek tersebut. Seccomp menentukan apakah invocation syscall mencapai implementasi kernel normalnya. Setelah sebuah call diizinkan, otorisasi biasa dan semantik objek dari subsystem terkait tetap mengatur operasi.

Kondisi ini menjadikan kebersihan descriptor bagian dari rancangan sandbox. Menutup descriptor yang tidak diperlukan, menerapkan FD_CLOEXEC atau flag close-on-exec saat pembuatan, mengurangi kredensial dan capabilities, membatasi namespace, serta menerapkan kebijakan Linux Security Module yang sesuai menangani otoritas yang tidak direpresentasikan filter syscall.

Komposisi lebih penting daripada keberadaan satu kontrol. Profil seccomp dapat mengurangi permukaan serangan kernel sementara LSM membatasi akses objek dan namespace mengubah visibilitas resource. Batas isolasi yang dihasilkan merupakan irisan mekanisme tersebut dan otoritas yang masih dimiliki proses.

Allowlist syscall adalah anggaran interface kernel

Seccomp paling kuat ketika perannya dinyatakan secara sempit. Allowlist mencatat entry point kernel yang boleh dicoba workload pada ABI dan state proses tertentu. Kebijakan ini dapat secara material mengurangi paparan terhadap kode kernel yang tidak diperlukan workload, serta mengubah penggunaan syscall yang tidak diharapkan menjadi kegagalan terkontrol.

Seccomp tidak dapat membuktikan bahwa operasi yang diizinkan bersifat aman. Mekanisme ini tidak dapat menyimpulkan kebijakan aliran data dari buffer aplikasi, mencabut ambient authority yang direpresentasikan objek terbuka, atau menggantikan otorisasi pada subsystem yang dicapai call yang diizinkan. Batas tersebut bukan celah di sekitar sandbox yang sebenarnya lengkap; batas tersebut mendefinisikan mekanismenya.

Rancangan confinement yang kuat karena itu memperlakukan profil seccomp sebagai anggaran interface kernel. Batas keamanan baru menjadi kredibel ketika anggaran tersebut digabungkan dengan kontrol eksplisit atas kredensial, objek, namespace, descriptor, dan supervisor apa pun yang dipercaya untuk memediasi call khusus.