Saat ini saya sedang mengerjakan sebuah proyek di mana saya memiliki proses induk yang mengatur socketpair, garpu dan kemudian menggunakan socketpair ini untuk berkomunikasi. Anak, jika ingin membuka file (atau sumber daya berbasis deskriptor file lainnya) harus selalu pergi ke orang tua, minta sumber dan dapatkan fd
dikirim melalui soketpair. Selanjutnya saya ingin mencegah anak dari membuka file descriptor dengan sendirinya.
Saya tersandung setrlimit
yang berhasil mencegah anak dari membuka deskriptor file baru, tetapi juga tampaknya membatalkan deskriptor file yang dikirim melalui koneksi socket awal. Apakah ada metode di Linux yang memungkinkan satu proses untuk membuka file apa pun, mengirim deskriptor file ke proses lain dan memungkinkan mereka menggunakannya tanpa mengizinkan proses lain ini untuk membuka file deskriptor sendiri?
Untuk kasus penggunaan saya yang dapat berupa konfigurasi kernel, panggilan sistem, dll. Asalkan dapat diterapkan setelah garpu dan selama itu berlaku untuk semua deskriptor file (bukan hanya file tetapi juga soket, soket, dll.).
sumber
Jawaban:
Apa yang Anda miliki di sini adalah kasus penggunaan seccomp .
Dengan menggunakan seccomp, Anda dapat memfilter panggilan sys dengan berbagai cara. Apa yang ingin Anda lakukan dalam situasi ini, tepat setelah
fork()
, untuk menginstalseccomp
filter yang melarang penggunaanopen(2)
,openat(2)
,socket(2)
(dan lebih). Untuk mencapai ini, Anda dapat melakukan hal berikut:seccomp_init(3)
dengan perilaku defaultSCMP_ACT_ALLOW
.seccomp_rule_add(3)
untuk setiap syscall yang ingin Anda tolak. Anda dapat menggunakanSCMP_ACT_KILL
untuk membunuh proses jika syscall dicoba,SCMP_ACT_ERRNO(val)
untuk membuat syscall gagal mengembalikan nilai yang ditentukanerrno
, atauaction
nilai lain yang ditentukan dalam halaman manual.seccomp_load(3)
untuk membuatnya efektif.Sebelum melanjutkan, CATATAN bahwa pendekatan daftar hitam seperti ini secara umum lebih lemah daripada pendekatan daftar putih. Ini memungkinkan syscall yang tidak dianulir secara eksplisit, dan dapat mengakibatkan bypass filter . Jika Anda yakin bahwa proses anak yang ingin Anda lakukan bisa berbahaya mencoba menghindari filter, atau jika Anda sudah tahu syscalls mana yang dibutuhkan oleh anak-anak, pendekatan daftar putih lebih baik, dan Anda harus melakukan kebalikan dari yang di atas: buat filter dengan aksi default
SCMP_ACT_KILL
dan izinkan syscall yang diperlukanSCMP_ACT_ALLOW
. Dalam hal kode perbedaannya minimal (daftar putih mungkin lebih lama, tetapi langkah-langkahnya sama).Berikut adalah contoh di atas (Saya melakukan
exit(-1)
jika ada kesalahan hanya karena kesederhanaan):Sekarang, di program Anda, Anda dapat memanggil fungsi di atas untuk menerapkan filter seccomp tepat setelah
fork()
, seperti ini:Beberapa catatan penting pada seccomp:
fork(2)
atauclone(2)
diizinkan oleh filter, setiap proses anak akan dibatasi oleh filter yang sama.execve(2)
diizinkan, filter yang ada akan dipertahankan pada panggilan keexecve(2)
.prctl(2)
syscall diizinkan, proses dapat menerapkan filter lebih lanjut.sumber
socket(2)
juga bisa buatfd
, sehingga harus diblokir juga. Jika Anda tahu proses anak, pendekatan daftar putih lebih baik.creat()
,dup()
, dandup2()
semua sistem Linux panggilan bahwa file kembali deskriptor. Ada banyak cara di sekitar daftar hitam ...