Ввод пространства имен монтирования перед настройкой a chroot
позволяет избежать загромождения пространства имен хоста дополнительными монтированиями, например, для /proc
. Вы можете использовать chroot
внутри пространства имен монтирования как приятный и простой взлом.
Я думаю, что у понимания есть свои преимущества pivot_root
, но у него есть некоторая кривая обучения. Документация не совсем объясняет все ... хотя есть пример использования man 8 pivot_root
(для команды оболочки). man 2 pivot_root
(для системного вызова) может быть более понятным, если бы он делал то же самое и включал пример программы на Си.
Как использовать pivot_root
Сразу после входа в пространство имен монтирования вам также потребуется mount --make-rslave /
или эквивалентный. В противном случае все ваши изменения монтирования распространяются на монтирования в исходном пространстве имен, включая pivot_root
. Вы не хотите этого :).
Если вы использовали unshare --mount
команду, обратите внимание, что она задокументирована для применения mount --make-rprivate
по умолчанию. AFAICS, это плохое значение по умолчанию, и вы не хотите этого в производственном коде. Например, на этом этапе он не сможет eject
работать на подключенном DVD или USB в пространстве имен хоста. DVD или USB останутся подключенными внутри частного дерева монтирования, и ядро не позволит вам извлечь DVD.
После этого вы можете смонтировать, например, /proc
каталог, который вы будете использовать. Так же, как и вы chroot
.
В отличие от того, когда вы используете chroot
, pivot_root
требует, чтобы ваша новая корневая файловая система была точкой монтирования. Если это не один уже, вы можете удовлетворить это, просто применяя привязка установки: mount --rbind new_root new_root
.
Используйте pivot_root
- и затем umount
старую корневую файловую систему, с-l
/ MNT_DETACH
. ( Вам не нужно umount -R
, что может занять больше времени. )
Технически, использование, pivot_root
как правило, должно включать использование chroot
; это не «или-или».
Согласно man 2 pivot_root
, он определяется только как замена корня пространства имен монтирования. Не определено, на какую физическую директорию указывает корень процесса. Или текущий рабочий каталог ( /proc/self/cwd
). Бывает, что так и есть, но это хак для обработки потоков ядра. На странице написано, что это может измениться в будущем.
Обычно вы хотите эту последовательность:
chdir(new_root); // cd new_root
pivot_root(".", put_old); // pivot_root . put_old
chroot("."); // chroot .
Пост chroot
в этой последовательности является еще одной тонкой деталью . Хотя смысл pivot_root
состоит в том, чтобы переставить пространство имен монтирования, кажется, что код ядра находит корневую файловую систему для перемещения, просматривая корень для каждого процесса, который и chroot
устанавливает.
Зачем использовать pivot_root
В принципе, имеет смысл использовать pivot_root
для безопасности и изоляции. Мне нравится думать о теории безопасности на основе возможностей . Вы передаете список необходимых ресурсов, и процесс не может получить доступ к другим ресурсам. В данном случае речь идет о файловых системах, передаваемых в пространство имен монтирования. Эта идея в целом применима к функции Linux "пространств имен", хотя я, вероятно, не очень хорошо ее выражаю.
chroot
только устанавливает корень процесса, но процесс все еще ссылается на полное пространство имен монтирования. Если процесс сохраняет привилегию для выполнения chroot
, он может выполнить обратное копирование пространства имен файловой системы. Как подробно описано вman 2 chroot
статье, «суперпользователь может сбежать из« тюрьмы chroot »с помощью ...».
Еще один заставляющий задуматься способ отменить chroot
это nsenter --mount=/proc/self/ns/mnt
. Возможно, это более сильный аргумент в пользу принципа. nsenter
/ setns()
обязательно перезагружает корень процесса из корня пространства имен монтирования ... хотя тот факт, что это работает, когда оба ссылаются на разные физические каталоги, может рассматриваться как ошибка ядра. (Техническое примечание: может быть несколько файловых систем, смонтированных поверх друг друга в корне; setns()
используется верхняя, самая последняя из которых смонтирована).
Это иллюстрирует одно преимущество объединения пространства имен монтирования с «пространством имен PID». Находясь внутри пространства имен PID, вы не сможете войти в пространство имен монтирования неограниченного процесса. Это также не позволяет вам войти в корень неограниченного процесса ( /proc/$PID/root
). И, конечно же, пространство имен PID также не позволяет вам убивать любой процесс, находящийся вне его :-).
pivot_root
иchroot
: я взглянул на исходные коды Docker и обнаружил, что если он не выполняетсяpivot_root
, он отступаетchroot
, т. Е. Эти механизмы считаются, по крайней мере, схожими по функциональности для целей контейнеризации.