Як виконати chroot за допомогою просторів імен Linux?


14

Прочитавши про простори імен Linux, у мене склалося враження, що вони, серед багатьох інших функцій, є альтернативою chroot. Наприклад, у цій статті :

Інші способи використання [просторів імен] включають в себе ізоляцію процесу [...] chroot () до частини ієрархії єдиного каталогу.

Однак, коли я клоную простір імен для монтування, наприклад, за допомогою наступної команди, я все ще бачу все оригінальне дерево коренів.

unshare --mount -- /bin/bash

Я розумію, що зараз я можу виконувати додаткові кріплення в новому просторі імен, які не поділяються з оригінальним простором імен, і, таким чином, це забезпечує ізоляцію, але це все одно той самий корінь, наприклад /etc, все ще однаковий для обох просторів імен. Мені все ж потрібно chrootзмінити корінь чи є альтернатива?

Я очікував, що це питання дасть відповідь, але відповідь chrootзнову використовується лише .

РЕДАКТИКА №1

Зараз уже було видалено коментар, який згадувався pivot_root. Оскільки це насправді є частиною linux/fs/namespace.c, воно фактично є частиною реалізації просторів імен. Це говорить про те, що змінювати кореневий каталог тільки за допомогою unshareта mountнеможливо, але простори імен надають власну - більш розумну - версію chroot. Проте я не розумію основної ідеї цього підходу, яка робить його принципово відмінним від chrootнавіть після прочитання вихідного коду (у сенсі, наприклад, безпека чи краща ізоляція).

ЗРІД №2

Це не дублікат цього питання . Після виконання всіх команд з відповіді я маю окремий /tmp/tmp.vyM9IwnKuY (або подібний), але кореневий каталог все одно той самий!


Щодо різниці між pivot_rootі chroot: я переглянув джерела Докера і виявив, що якщо його не виконати pivot_root, він повертається назад chroot, тобто ці механізми вважаються принаймні схожими за функціональністю для цілей контейнерації.
Даніла Ківер

Відповіді:


13

Введення простору імен для монтування перед налаштуванням a chrootдозволяє уникнути захаращення простору імен хоста додатковими кріпленнями, наприклад, для /proc. Ви можете використовувати chrootвсередині простору імен кріплення як гарний і простий хак.

Я думаю, що в розумінні є переваги pivot_root, але це має трохи криву навчання. Документація не зовсім пояснює все, хоча є приклад використання в man 8 pivot_root(для команди shell). man 2 pivot_root(для системного виклику) може бути зрозумілішим, якби це робилося те саме, і включив приклад програми C.

Як користуватися 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 також не дозволяє вбити будь-який процес, що знаходиться поза нею :-).


Це вже дуже допомагає. Але я не впевнений, що ви маєте на увазі під "кріпленням у верхній частині простору імен". І чи є спосіб це змінити?
koalo

1
@koalo відредагував :-). ps Я не знаю, чому вам знадобиться fstab для "make-rslave" / "make-rprivate". systemd's switch-root.c щойно робитьmount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL)
sourcejedi

1
@koalo, а потім розробники ядра Linux використовували "rootfs", коли вони називали четверту річ :-P. unix.stackexchange.com/questions/152029/…
sourcejedi

1
Ця відповідь та інші користувачі @sourcejedi були надзвичайно корисними, я б попросив "pivot_root: не можна порахувати put_old як зайнятий", але відповідь уже був тут, лінуйся, бо сила не спрацюєumount -l ./oldroot
earcam

1
Нещодавно з'явилося оновлення сторінки man на pivot_root (2) з кількома уточненнями, і тепер вона включає приклад програми. Ви можете оновити свою відповідь, щоб це відобразити? Сторінка "man" тепер також пояснює приємний pivot_root(".", ".")трюк, який насправді найпростіший спосіб використання pivot_rootв більшості обставин (не chrootпотрібно).
Філіп Вендлер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.