Libseccomp: T: tidak dapat memiliki filter yang berbeda dengan SCMP_ACT_NOTIFY di utas yang berbeda

Dibuat pada 6 Nov 2020  ·  9Komentar  ·  Sumber: seccomp/libseccomp

libseccomp menyimpan notifikasi fd dalam variabel global: state.notify_fd . Hal ini membuat tidak mungkin untuk menggunakan libseccomp untuk aplikasi multi-utas dengan filter berbeda di utas berbeda (yaitu tanpa menggunakan TSYNC).

libseccomp memiliki seccomp_reset(NULL, ...) untuk mereset variabel global state.notify_fd . Tetapi seccomp_reset() memiliki konsekuensi yang tidak menguntungkan untuk mengatur ulang state.nr_seccomp = -1 .

Masalah ini diperhatikan ketika mencoba menyelesaikan pengujian unit di libseccomp-golang, lihat https://github.com/seccomp/libseccomp-golang/pull/59#issuecomment -723045033

cc @yvesf @rata

prioritlow question

Komentar yang paling membantu

Sepertinya kita semua setuju di sini jadi saya akan menutup masalah ini. @alban jika menurut Anda kami melewatkan sesuatu yang penting, beri tahu kami dan/atau buka kembali masalah ini sehingga kami dapat menyelesaikan semuanya.

Terimakasih semuanya.

Semua 9 komentar

@drakenclimber menahan rilis v2.5.1 yang akan datang sampai kami mendapatkan klarifikasi tentang ini. Saya tidak yakin saya sepenuhnya memahami laporan aslinya, tetapi karena v2.5.1 adalah rilis pertama yang mengimplementasikan konsep seccomp_reset(NULL, ...) , mari kita tunggu sebentar sampai kita dapat memverifikasi semuanya ...

Menambahkan ini ke tonggak v2.5.1 hanya sebagai pemblokir untuk saat ini, ini dapat berubah saat kami menyelidiki berbagai hal.

@drakenclimber menahan rilis v2.5.1 yang akan datang sampai kami mendapatkan klarifikasi tentang ini. Saya tidak yakin saya sepenuhnya memahami laporan aslinya, tetapi karena v2.5.1 adalah rilis pertama yang mengimplementasikan konsep seccomp_reset(NULL, ...) , mari kita tunggu sebentar sampai kita dapat memverifikasi semuanya ...

Sepakat. Akan melakukan.

libseccomp menyimpan notifikasi fd dalam variabel global: state.notify_fd . Hal ini membuat tidak mungkin untuk menggunakan libseccomp untuk aplikasi multi-utas dengan filter berbeda di utas berbeda (yaitu tanpa menggunakan TSYNC).

Bisakah Anda menguraikan sedikit lebih banyak tentang kalimat terakhir itu? Saya tidak yakin saya mengerti apa yang Anda coba sampaikan.

FWIW, FD notifikasi seccomp adalah objek global proses, Anda hanya dapat memintanya dari kernel satu kali. Anda dapat membaca https://github.com/seccomp/libseccomp/issues/273 untuk mendapatkan lebih banyak latar belakang tentang masalah ini.

libseccomp memiliki seccomp_reset(NULL, ...) untuk mereset variabel global state.notify_fd . Tetapi seccomp_reset() memiliki konsekuensi yang tidak menguntungkan untuk mengatur ulang state.nr_seccomp = -1 .

Mengapa menyetel ulang state.nr_seccomp = -1 merupakan masalah yang signifikan? Jika bidang nr_seccomp direset ke -1 saat berikutnya diminta operasi yang dapat menggunakan seccomp(2) perpustakaan memeriksa untuk melihat apakah seccomp(2) didukung dan menggunakannya jika tersedia. Ya, itu bisa menghasilkan panggilan tambahan ke seccomp(2) tetapi itu seharusnya tidak menjadi masalah besar, apakah ini masalah untuk kasus penggunaan Anda?

@alban - Pertanyaan serupa dari saya. Saya menghabiskan sedikit waktu untuk mencoba menemukan kasus penggunaan multi-utas, multi-seccomp-filter yang masuk akal (dalam C) dan benar-benar tidak dapat menemukan apa pun.

Saya membaca dokumentasi Go os.LockOSThread() , dan itu masuk akal bagi saya. Tetapi saya berjuang untuk mengubah pengetahuan ini menjadi solusi multi-utas, multi-detik-filter.

Bisakah Anda membagikan beberapa kode semu atau desain tingkat tinggi dari apa yang Anda pikirkan? Saya akan dengan senang hati membuat prototipe di C saat itu.

Bisakah Anda menguraikan sedikit lebih banyak tentang kalimat terakhir itu? Saya tidak yakin saya mengerti apa yang Anda coba sampaikan.

Saat mengerjakan tes unit di libseccomp-golang, saya menyadari bahwa skenario berikut sedang diuji:

  1. Dalam eksekusi pertama unit test, kebijakan seccomp diterapkan tanpa SECCOMP_FILTER_FLAG_TSYNC (artinya diterapkan pada tingkat utas dan bukan pada tingkat proses) tetapi dengan SECCOMP_FILTER_FLAG_NEW_LISTENER (jadi libseccomp akan menyimpan fd di state.notify_fd ).
  2. Tes unit yang sama dijalankan lagi dalam proses yang sama tetapi di utas yang berbeda (menggunakan runtime.LockOSThread di Go untuk memastikannya). Tetapi libseccomp menggunakan kembali fd dari filter seccomp sebelumnya (dari state.notify_fd ) alih-alih mendapatkan fd baru untuk filter baru. Kemudian tes gagal karena kami berharap menerima acara di seccomp fd yang salah.

FWIW, FD notifikasi seccomp adalah objek global proses, Anda hanya dapat memintanya dari kernel satu kali. Anda dapat membaca #273 untuk mendapatkan lebih banyak latar belakang tentang masalah ini.

Dari apa yang saya pahami, kernel membatasi kita untuk mendapatkan hanya satu FD notifikasi detik di pohon filter. Tetapi dalam skenario di atas, dua utas dari proses yang sama menggunakan pohon filter yang berbeda, sehingga seharusnya baik-baik saja dari perspektif kernel.

Skenario untuk menggunakan pohon filter yang berbeda dengan SECCOMP_FILTER_FLAG_NEW_LISTENER ini tidak dibuat dengan sengaja, itu hanya muncul sebagai konsekuensi dari pengujian unit libseccomp-golang yang berjalan dalam proses yang sama. Tetapi karena akar masalahnya adalah libseccomp menggunakan variabel global state.notify_fd yang dibagi di antara utas, saya pikir saya harus membuka bug ini di sini untuk membuka diskusi. Namun saya akan baik-baik saja jika ini ditutup sebagai "WONTFIX" (Saya tidak tahu apakah pengguna libseccomp lain perlu memiliki dukungan untuk skenario semacam ini). Dalam hal ini, kita hanya dapat menulis pengujian unit libseccomp-golang dengan cara yang berbeda (yaitu menggunakan proses terpisah untuk setiap iterasi pengujian); kita harus tetap melakukannya (untuk menghindari pencampuran filter level utas dan filter level proses - yang akan ditolak oleh kernel).

Saat mengerjakan tes unit di libseccomp-golang, saya menyadari bahwa skenario berikut sedang diuji:

  1. Dalam eksekusi pertama unit test, kebijakan seccomp diterapkan tanpa SECCOMP_FILTER_FLAG_TSYNC (artinya diterapkan pada tingkat utas dan bukan pada tingkat proses) tetapi dengan SECCOMP_FILTER_FLAG_NEW_LISTENER (jadi libseccomp akan menyimpan fd di state.notify_fd ).
  2. Tes unit yang sama dijalankan lagi dalam proses yang sama tetapi di utas yang berbeda (menggunakan runtime.LockOSThread di Go untuk memastikannya). Tetapi libseccomp menggunakan kembali fd dari filter seccomp sebelumnya (dari state.notify_fd ) alih-alih mendapatkan fd baru untuk filter baru. Kemudian tes gagal karena kami berharap menerima acara di seccomp fd yang salah.

Ah ha, itu lebih masuk akal sekarang. Saya sering bertanya-tanya apakah kita harus menjadikan TSYNC sebagai default untuk binding libseccomp-golang; mengingat ambiguitas utas di Go sepertinya pilihan yang jauh lebih aman.

Dari apa yang saya pahami, kernel membatasi kita untuk mendapatkan hanya satu FD notifikasi detik di pohon filter. Tetapi dalam skenario di atas, dua utas dari proses yang sama menggunakan pohon filter yang berbeda, sehingga seharusnya baik-baik saja dari perspektif kernel.

Skenario untuk menggunakan pohon filter yang berbeda dengan SECCOMP_FILTER_FLAG_NEW_LISTENER ini tidak dibuat dengan sengaja, itu hanya muncul sebagai konsekuensi dari pengujian unit libseccomp-golang yang berjalan dalam proses yang sama. Tetapi karena akar masalahnya adalah libseccomp menggunakan variabel global state.notify_fd yang dibagi di antara utas, saya pikir saya harus membuka bug ini di sini untuk membuka diskusi. Namun saya akan baik-baik saja jika ini ditutup sebagai "WONTFIX" (Saya tidak tahu apakah pengguna libseccomp lain perlu memiliki dukungan untuk skenario semacam ini). Dalam hal ini, kita hanya dapat menulis pengujian unit libseccomp-golang dengan cara yang berbeda (yaitu menggunakan proses terpisah untuk setiap iterasi pengujian); kita harus tetap melakukannya (untuk menghindari pencampuran filter level utas dan filter level proses - yang akan ditolak oleh kernel).

Saya akan tertarik untuk mendapatkan pendapat @drakenclimber tentang ini, tetapi ya pemikiran saya sekarang adalah bahwa ini adalah "WONTFIX" karena ini adalah kasus sudut yang agak aneh. Jika aplikasi memang ingin melakukan hal seperti ini, mereka dapat menyimpan fd notifikasi dari pohon filter "A", mengatur ulang libseccomp, lalu mengambil dan menyimpan notifikasi fd dari pohon filter "B".

Untuk "memperbaiki" ini di libseccomp, kita perlu membuat utas libseccomp sadar, yang datang dengan sejumlah tantangan dan jebakan, sehingga saat ini saya berpendapat bahwa ini akan menjadi Ide Buruk. Namun, demi argumen, jika kami membuat libseccomp thread sadar, kami juga dapat membuat status global internal menjadi status khusus utas dan/atau mungkin status khusus pohon filter; dalam salah satu dari kasus ini saya pikir API saat ini (termasuk seccomp_reset(NULL, ...) ) masih masuk akal jadi saya tergoda untuk membiarkan hal-hal apa adanya dengan API. Jika ada yang khawatir tentang itu, beri tahu kami segera.

@drakenclimber? Kecuali ada keberatan atas hal di atas, saya pikir kami kembali untuk rilis v2.5.1.

Saya akan tertarik untuk mendapatkan pendapat @drakenclimber tentang ini, tetapi ya pemikiran saya sekarang adalah bahwa ini adalah "WONTFIX" karena ini adalah kasus sudut yang agak aneh. Jika aplikasi memang ingin melakukan hal seperti ini, mereka dapat menyimpan fd notifikasi dari pohon filter "A", mengatur ulang libseccomp, lalu mengambil dan menyimpan notifikasi fd dari pohon filter "B".

Saya setuju. Saya menghabiskan beberapa waktu untuk menggali patchset dan komentar asli @tych0 serta kode kernel itu sendiri. Kasus penggunaan yang dia bayangkan adalah proses pemantauan yang menjalankan handler notifikasi sementara proses kemas datang dan pergi. Ketika proses dalam container ini memanggil syscall yang memiliki notifikasi di dalamnya, proses pemantauan dapat melakukan logika tambahan untuk mengizinkan/menolak permintaan tersebut.

Dengan itu, saya mencoba membuat kasus penggunaan multi-utas, proses tunggal yang memiliki banyak pemanggil dan penangan notifikasi. Sejujurnya, saya tidak bisa secara koheren menyusun skenario seperti itu. Karena ini adalah kasus penggunaan yang agak dibuat-buat, dan saya tidak dapat menemukan kasus penggunaan yang realistis, kita harus menandai WONTFIX ini.

Di samping satu - saya bisa mendapatkan kernel untuk mengembalikan beberapa fds pemberitahuan ke suatu proses. Dengan membuat beberapa pthreads dan membuat semuanya segera memuat filter seccomp dengan tindakan notifikasi, kadang-kadang saya bisa mendapatkan dua atau tiga notifikasi berbeda yang dikembalikan ke proses ruang pengguna. Karena ini sangat tidak realistis, saya akan cenderung menandai masalah kernel ini sebagai WONTFIX juga.

@drakenclimber? Kecuali ada keberatan atas hal di atas, saya pikir kami kembali untuk rilis v2.5.1.

Besar. Saya harus bisa mulai mengerjakannya awal minggu depan.

Sepertinya kita semua setuju di sini jadi saya akan menutup masalah ini. @alban jika menurut Anda kami melewatkan sesuatu yang penting, beri tahu kami dan/atau buka kembali masalah ini sehingga kami dapat menyelesaikan semuanya.

Terimakasih semuanya.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat