Bagaimana cara melakukan chroot dengan ruang nama Linux?


14

Setelah membaca tentang ruang nama Linux saya mendapat kesan bahwa mereka, di antara banyak fitur lainnya, merupakan alternatif untuk chroot. Misalnya, dalam artikel ini :

Kegunaan lain [dari namespaces] termasuk [...] chroot () - gaya isolasi suatu proses ke bagian dari hirarki direktori tunggal.

Namun, ketika saya mengkloning mount namespace, misalnya dengan perintah berikut, saya masih melihat seluruh root tree asli.

unshare --mount -- /bin/bash

Saya mengerti bahwa saya sekarang dapat melakukan mount tambahan di namespace baru yang tidak dibagi dengan namespace asli dan dengan demikian ini menyediakan isolasi, tetapi masih root yang sama, misalnya /etcmasih sama untuk kedua namespace. Apakah saya masih perlu chrootmengubah root atau ada alternatif?

Saya mengharapkan pertanyaan ini akan memberikan jawaban, tetapi jawabannya hanya menggunakan chroot, lagi.

EDIT # 1

Ada komentar yang sekarang dihapus yang menyebutkan pivot_root. Karena ini sebenarnya bagian dari linux/fs/namespace.c, itu sebenarnya bagian dari implementasi namespaces. Ini menunjukkan bahwa mengubah direktori root hanya dengan unsharedan mounttidak mungkin, tetapi namespaces menyediakan versi sendiri - yang lebih pintar chroot. Masih saya tidak mendapatkan ide utama dari pendekatan ini yang membuatnya berbeda secara mendasar chroot, bahkan setelah membaca kode sumber (dalam arti keamanan misalnya atau isolasi yang lebih baik).

EDIT # 2

Ini bukan duplikat dari pertanyaan ini . Setelah menjalankan semua perintah dari jawaban saya memiliki /tmp/tmp.vyM9IwnKuY yang terpisah (atau serupa), tetapi direktori root masih sama!


Mengenai perbedaan antara pivot_rootdan chroot: Saya melihat sumber-sumber Docker dan menemukan bahwa jika gagal dieksekusi pivot_root, ia kembali ke chroot, yaitu mekanisme ini dianggap setidaknya sama dalam fungsi untuk keperluan kontainerisasi.
Danila Kiver

Jawaban:


13

Memasuki mount namespace sebelum mengatur a chroot, memungkinkan Anda menghindari mengacaukan namespace host dengan mount tambahan, misalnya untuk /proc. Anda dapat menggunakan chrootdi dalam mount namespace sebagai retasan yang bagus dan sederhana.

Saya pikir ada keuntungan untuk memahami pivot_root, tetapi memiliki sedikit kurva pembelajaran. Dokumentasi tidak menjelaskan semuanya ... meskipun ada contoh penggunaan di man 8 pivot_root(untuk perintah shell). man 2 pivot_root(untuk panggilan sistem) mungkin lebih jelas jika melakukan hal yang sama, dan termasuk contoh program C.

Cara menggunakan pivot_root

Segera setelah memasuki mount namespace, Anda juga perlu mount --make-rslave /atau setara. Jika tidak, semua perubahan mount Anda menyebar ke mount di namespace asli, termasuk pivot_root. Anda tidak mau itu :).

Jika Anda menggunakan unshare --mountperintah, catat itu didokumentasikan untuk diterapkan mount --make-rprivatesecara default. AFAICS ini adalah default yang buruk dan Anda tidak ingin ini dalam kode produksi. Misalnya pada titik ini, itu akan berhenti ejectbekerja pada DVD atau USB yang terpasang di host namespace. DVD atau USB akan tetap terpasang di dalam pohon mount pribadi, dan kernel tidak akan membiarkan Anda mengeluarkan DVD.

Setelah Anda selesai melakukannya, Anda dapat memasang mis. /procDirektori yang akan Anda gunakan. Cara yang sama Anda lakukan untuk chroot.

Tidak seperti ketika Anda menggunakan chroot, pivot_rootmengharuskan sistem file root baru Anda adalah titik pemasangan. Jika tidak satu sudah, Anda dapat memuaskan ini dengan hanya menerapkan mengikat mount: mount --rbind new_root new_root.

Gunakan pivot_root- dan kemudian umountfilesystem root lama, dengan opsi -l/ MNT_DETACH. ( Anda tidak perlu umount -R, yang bisa lebih lama. ).

Secara teknis, menggunakan pivot_rootsecara umum perlu melibatkan penggunaan chrootjuga; itu bukan "salah satu atau".

Per man 2 pivot_root, itu hanya didefinisikan sebagai menukar root dari mount namespace. Itu tidak didefinisikan untuk mengubah direktori fisik yang ditunjuk oleh root proses. Atau direktori kerja saat ini ( /proc/self/cwd). Hal ini terjadi bahwa hal itu tidak melakukannya, tapi ini adalah hack untuk benang menangani kernel. Halaman buku itu mengatakan bahwa itu bisa berubah di masa depan.

Biasanya Anda menginginkan urutan ini:

chdir(new_root);            // cd new_root
pivot_root(".", put_old);   // pivot_root . put_old
chroot(".");                // chroot .

Posisi chrootdalam urutan ini adalah detail halus lainnya . Walaupun intinya pivot_rootadalah mengatur ulang mount namespace, kode kernel tampaknya menemukan filesystem root untuk dipindahkan dengan melihat root per-proses, yang merupakan apa yang chrootditetapkan.

Mengapa menggunakan pivot_root

Pada prinsipnya, masuk akal untuk digunakan pivot_rootuntuk keamanan dan isolasi. Saya suka berpikir tentang teori keamanan berbasis kemampuan . Anda memasukkan daftar sumber daya spesifik yang diperlukan, dan proses tidak dapat mengakses sumber daya lain. Dalam hal ini kita berbicara tentang filesystem yang diteruskan ke mount namespace. Ide ini umumnya berlaku untuk fitur "namespaces" Linux, meskipun saya mungkin tidak mengekspresikannya dengan baik.

chroothanya menetapkan root proses, tetapi prosesnya masih mengacu pada namespace mount lengkap. Jika suatu proses tetap memiliki hak istimewa untuk melakukan chroot, maka itu dapat melintasi kembali namespace sistem file. Sebagaimana dirinci dalam man 2 chroot, "superuser dapat melarikan diri dari 'chroot jail' dengan ...".

Cara lain yang memicu pemikiran untuk membatalkan chrootadalah nsenter --mount=/proc/self/ns/mnt. Ini mungkin argumen yang lebih kuat untuk prinsip ini. nsenterSaya setns()perlu memuat ulang root proses, dari root mount namespace ... walaupun fakta bahwa ini berfungsi ketika keduanya merujuk ke direktori fisik yang berbeda, dapat dianggap sebagai bug kernel. (Catatan teknis: mungkin ada beberapa sistem file yang dipasang di atas satu sama lain di root; setns()menggunakan bagian atas, yang terbaru dipasang).

Ini menggambarkan satu keuntungan dari menggabungkan namespace mount dengan "namespace PID". Berada di dalam namespace PID akan mencegah Anda memasuki mount namespace dari proses yang tidak terbatas. Ini juga mencegah Anda memasukkan root dari proses yang tidak dibatasi ( /proc/$PID/root). Dan tentu saja namespace PID juga mencegah Anda membunuh proses apa pun yang ada di luarnya :-).


Ini sudah banyak membantu. Namun, saya tidak yakin apa yang Anda maksud dengan "mount di bagian atas namespace". Dan adakah cara untuk mengubahnya?
koalo

1
@ Koalo diedit :-). ps saya tidak tahu mengapa Anda perlu fstab untuk "make-rslave" / "make-rprivate". switch-root.c systemd hanya melakukanmount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL)
sourcejedi

1
@ Koalo dan kemudian pengembang kernel linux menggunakan "rootfs" ketika mereka menyebutkan hal keempat :-P. unix.stackexchange.com/questions/152029/...
sourcejedi

1
Jawaban ini dan yang lainnya oleh @sourcejedi telah sangat membantu, saya akan bertanya "pivot_root: tidak dapat menganggap sibuk sibuknya" tetapi jawabannya sudah ada di sini, umount -l ./oldroot
malaslah

1
Baru-baru ini ada pembaruan ke halaman manual pivot_root (2) dengan beberapa klarifikasi, dan sekarang termasuk contoh program. Anda mungkin ingin memperbarui jawaban Anda untuk mencerminkan ini? Halaman manual sekarang juga menjelaskan pivot_root(".", ".")trik yang bagus , yang sebenarnya merupakan cara termudah untuk digunakan pivot_rootdalam sebagian besar keadaan (tidak chrootperlu).
Philipp Wendler
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.