Cara yang andal untuk memenjarakan proses anak menggunakan `nsenter:`

15

Saya tahu bahwa ruang nama Linux, di antara banyak hal lain, dapat dimanfaatkan untuk menangani pembatasan dan memenjarakan proses anak dengan aman tanpa ada kemungkinan mereka diserang dan dibuang init. Tapi saya tidak jelas tentang detail implementasi. Bagaimana saya bisa menggunakan alat yang disediakan oleh util-linuxseperti mountdan nsenteruntuk menonton, memantau, dan memastikan bahwa semua proses yang diluncurkan adalah keturunan namespace langsung dari proses lain?

mikeserv
sumber

Jawaban:

19

Buat namespace PID

Perintah yang benar untuk digunakan di sini adalah unshare. Perhatikan bahwa opsi yang diperlukan untuk melakukan ini hanya tersedia dari util-linux 2.23. Idenya adalah untuk membuat namespace PID baru untuk program yang Anda jalankan sehingga semua anak-anaknya juga dibuat di namespace ini. Anda dapat menjalankan perintah di namespace PID baru hanya dengan melakukan:

sudo unshare -fp some_command

Untuk menjalankan shell, abaikan saja perintahnya. Ini akan membuat proses yang, bersama dengan anak-anaknya, akan memiliki PID seperti biasa di dalam ruang nama orang tua (sistem). Namun, di dalam namespace baru, itu akan memiliki PID 1bersama dengan beberapa karakteristik khusus dari initproses tersebut. Mungkin karakteristik yang paling relevan dari perspektif pemantauan adalah bahwa jika salah satu dari keturunannya menjadi yatim piatu, mereka akan dipasangkan kembali ke proses ini daripada proses yang sebenarnya init.

Cukup melakukan ini mungkin cukup untuk sebagian besar kasus pemantauan. Seperti disebutkan sebelumnya, proses-proses dalam namespace semua memiliki PID di dalam namespace induk sehingga perintah biasa dapat digunakan untuk memantau aktivitas mereka. Kami juga yakin bahwa jika proses apa pun di namespace menjadi yatim piatu, tidak akan jatuh dari cabang-cabang pohon proses di bawah PID dari program tingkat atas yang berarti bahwa ia masih dapat dengan mudah dilacak.

Gabungkan dengan mount namespace

Namun, yang tidak bisa kita lakukan adalah memantau proses sehubungan dengan PID yang menurutnya sudah. Untuk melakukan ini, dan khususnya untuk dapat menggunakan psperintah di dalam namespace baru, Anda perlu me-mount procfssistem file yang terpisah untuk namespace. Ini pada gilirannya menyebabkan masalah lain karena satu-satunya lokasi yang psmenerima procfsadalah /proc. Salah satu solusinya adalah membuat chrootpenjara dan memasang yang baru di procfssana. Tapi ini adalah pendekatan yang rumit karena setidaknya kita perlu menyalin (atau setidaknya hard link) setiap biner yang ingin kita gunakan bersama dengan perpustakaan yang mereka bergantung pada root baru.

Solusinya adalah juga menggunakan namespace mount baru . Dalam hal ini kita dapat memasang yang baru procfsdengan cara yang menggunakan /procdirektori root yang sebenarnya , dapat digunakan dalam namespace PID dan tidak mengganggu yang lain. Untuk membuat proses ini sangat sederhana, unshareperintah memberikan --mount-procopsi:

sudo unshare -fp --mount-proc some_command

Sekarang berjalan psdalam ruang nama gabungan hanya akan menunjukkan proses dengan namspace PID dan itu akan menunjukkan proses tingkat atas memiliki PID 1.

Bagaimana dengan nsenter?

Seperti namanya, nsenterdapat digunakan untuk memasukkan namespace yang sudah dibuat dengan unshare. Ini berguna jika kita ingin mendapatkan informasi yang hanya tersedia dari dalam namespace dari skrip yang tidak terkait. Cara paling sederhana adalah dengan mengakses berikan PID dari setiap program yang berjalan dalam namespace. Untuk menjadi jelas ini harus menjadi PID dari program target dalam namespace dari mana nsentersedang dijalankan (karena namespaces dapat disarangkan, dimungkinkan untuk satu proses memiliki banyak PID). Untuk menjalankan shell di PID / mount namespace target, cukup lakukan:

sudo nsenter -t $PID -m -p

Jika namespace ini diatur seperti di atas, pssekarang hanya akan mencantumkan proses dalam namespace itu.

Graeme
sumber
Terima kasih, Graeme. Ini sudah menjawab pertanyaan dan banyak lagi. Yang sebenarnya membuat saya bertanya adalah membaca catatan dari halaman manual procfs pada berbagai file di / proc / pid / ns / * yang mengatakan: "Bind me-mount file ini (lihat mount (2)) ke tempat lain di filesystem menyimpan ... namespace dari proses yang ditentukan oleh pid hidup bahkan jika semua proses saat ini dalam namespace berakhir. " Pertanyaan yang hampir sama, saya tahu, tapi ini sudah sangat bagus saya pikir jika Anda merasa itu relevan, Anda mungkin ingin menambahkannya. Linux.die.net/man/5/proc
mikeserv
Ini tercakup dalam bagian terakhir artikel LWN (cukup cari bind mount). Saya tidak begitu yakin maksudnya karena itu membuat namespace PID tetap hidup tetapi setelah initproses gaya tingkat atas mati, Anda tidak dapat membuat lagi.
Graeme
Ya, saya juga tidak terlalu yakin tentang sisanya. Tapi dengan jawaban ini dan manakhir pekan untuk diriku sendiri, aku bermaksud sedikit lebih akrab dengannya. Terima kasih lagi. Mungkin lebih relevan di --user namespace.
mikeserv