Як я можу сказати, що я бігаю в chroot?


47

У мене встановлення Unix, яке повинно бути корисним і як chroot, і як автономна система. Якщо він працює як chroot, я не хочу запускати будь-яку службу (cron, inetd тощо), тому що вони конфліктували б з хост-системою або були зайвими.

Як написати сценарій оболонки, який поводиться по-різному, залежно від того, працює він у chroot? Моя нагальна потреба - це сучасна система Linux, /procвмонтована в chroot, і сценарій працює як root, але більш портативні відповіді також вітаються. (Див. Як я можу сказати, що я працює в chroot, якщо / proc не встановлений? Для випадку Linux без /proc.)

Загалом, пропозиції, які працюють для інших методів стримування, були б цікавими. Практичне питання полягає в тому, чи повинна ця система працювати з якимись послугами? (Відповідь - ні в хротоні, а так - у повноцінних віртуальних машинах; я не знаю про проміжні випадки, такі як в'язниці чи контейнери.)

Відповіді:


46

Я тут зробив те, щоб перевірити, чи корень initпроцесу (PID 1) такий, як корінь поточного процесу. Хоча /proc/1/rootце завжди посилання на /(якщо тільки initне вказано, але це мене не хвилює), наступне воно веде до "головного" кореневого каталогу. Ця методика використовується в кількох сценаріях технічного обслуговування в Debian, наприклад, для пропуску початкового udev після встановлення в chroot.

if [ "$(stat -c %d:%i /)" != "$(stat -c %d:%i /proc/1/root/.)" ]; then
  echo "We are chrooted!"
else
  echo "Business as usual"
fi

(До речі, це ще один приклад того, чому chrootвін марний для безпеки, якщо до хронізованого процесу є кореневий доступ. Некореневі процеси не можуть читати /proc/1/root, але вони можуть слідувати, /proc/1234/rootякщо є запущений процес з PID 1234, який працює як той самий користувач.)

Якщо у вас немає прав суперкористувача, ви можете подивитися на /proc/1/mountinfoі /proc/$$/mountinfo(коротко описані в filesystems/proc.txtв документації ядра Linux ). Цей файл читається у всьому світі та містить багато інформації про кожну точку монтажу в режимі подання файлової системи. Шлях у цьому файлі обмежується chroot, що впливає на читацький процес, якщо такий є. Якщо зчитування процесу /proc/1/mountinfoхроноване у файлову систему, що відрізняється від глобального кореня (якщо припустимо, що корінь pid 1 є глобальним коренем), то в ньому не /відображається жодна запис /proc/1/mountinfo. Якщо читання процесу /proc/1/mountinfoє ізольованим в каталог на глобальній кореневої файлової системи, то запис для /з'являюся в /proc/1/mountinfo, але з іншим ідентифікатором монтування. До речі, кореневе поле ($4) вказує, де chroot знаходиться в його головній файловій системі.

[ "$(awk '$5=="/" {print $1}' </proc/1/mountinfo)" != "$(awk '$5=="/" {print $1}' </proc/$$/mountinfo)" ]

Це чисте рішення для Linux. Це може бути узагальнювальним для інших варіантів Unix з досить схожим /proc(у Solaris є подібний /proc/1/root, я думаю, але ні mountinfo).


1
Це не працюватиме у OpenBSD, оскільки він має випадкові PID ; кореневий процес в основному ніколи не PID 1. Тепер ви знаєте, чому!
Адам Кац

@AdamKatz "... з кількома очевидними винятками, наприклад, init (8)." Так що це?
муру

@muru: aw, shucks. Ти мене збив. Я не впевнений, чому init(8)б абсолютно потрібен слот №1, якщо не існує якогось жорсткого коду, який цього вимагає (в якому я все ще не знаю, чому ). Звичайно, у БСД є набагато більш розвинені в'язниці, ніж просто chroot, тому я навіть не впевнений, наскільки це проблематично.
Адам Кац

4
@AdamKatz Це навпаки: pid 1 відіграє особливу роль (він повинен пожинати зомбі, і він несприйнятливий до SIGKILL). Програма init - це реалізація цієї ролі. Причина, що моя відповідь не працює в OpenBSD, не має нічого спільного з цим: це тому, що OpenBSD не має нічого подібного до Solaris / Linux /proc. Моя відповідь все-таки не мала на меті вирішувати нічого, окрім Linux.
Жил "ТАК - перестань бути злим"

@Gilles Я подумав, що OpenBSD так чи інакше зазнає поразки. Тим не менш, я здивований, що всі ці особливі рольові позиції не можуть бути застосовані до довільного PID (без наслідків), що я мав на увазі в своєму курсивному курсі "чому" раніше.
Адам Кац

22

Як уже згадувалися в портативному способі знайти номер індексного дескриптора і виявлення CHROOT в'язниці зсередини , ви можете перевірити , є чи індексний дескриптором /є 2:

$ ls -di /
2 /

Число inode, яке відрізняється від 2, вказує на те, що видимий корінь не є фактичним коренем файлової системи. Це не виявить хрооти, які трапляються вкоріненими в точці монтажу, або в операційних системах з випадковими числами кореневих інод .


На яких файлових системах працює ця евристична робота?
Жиль "ТАК - перестань бути злим"

Тестували на ext3 та hfs.
l0b0

Тож я обдурив, і я думаю, що знайшов більш надійний метод, який не потребує кореневих дозволів (лише для Linux). Я все ще відкритий для зустрічних прикладів або більш портативних методів.
Жил 'SO- перестань бути злим'

6
Це справедливо для ext [234], але не для всіх файлових систем. Він також перевіряє лише те, що ваш корінь є коренем файлової системи, який може бути встановлений не як справжній корінь. Іншими словами, якщо ви змонтуєте інший розділ у / в'язниці і chroot /jail, це буде схоже на справжній корінь цього тесту.
psusi

1
@AdamKatz Мабуть, ні. Випробуваний у openbsd 6.0-стабільному, номер inode все ще 2 для фактичного кореневого шляху, тоді як це випадкове число для chroot.
Дмитро ДБ

5

Хоча явно не настільки портативний, як багато інших перерахованих тут параметрів, якщо ви працюєте на базі системи Debian, спробуйте ischroot.

Дивіться: https://manpages.debian.org/jessie/debianutils/ischroot.1.en.html

Щоб отримати статус у консолі безпосередньо, використовуйте ischroot:

ischroot;echo $?

Вихідні коди:

0 if currently running in a chroot
1 if currently not running in a chroot
2 if the detection is not possible (On GNU/Linux this happens if the script is not run as root).
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.