Странное поведение pivot_root(".", ".") в пространстве имен монтирования

Странное поведение pivot_root(".", ".") в пространстве имен монтирования

Я пытаюсь разобраться в контейнерах и наткнулся на трюк, по-видимому, найденный разработчиками LXC, см.этот PR рунк: Вы можете вызвать pivot_root(".", "."), который избегает необходимости в каталоге для размещения старого корня. Однако это заставляет пространство имен монтирования вести себя странно:

unshare --user --map-root-user --mount bash -c "
mount --bind containerfs bindmountpoint
cd bindmountpoint
pivot_root . .
# this is fine:
ls -l /
# this is not fine:
ls -l /..
"

Родительский элемент ., доступ к которому осуществляется через ./..или /..или , /proc/<any>/cwd/..указывает на корень пространства имен корневого монтирования (я еще не пробовал вкладывать)! Он не указывает на родителя containerfsnor bindmountpoint, а на самом деле на корень пространства имен корневого/внешнего монтирования.

Аналогично, когда я пробую nsenter --user --preserve-credentials --mount --target=<pid>, то этот новый процесс помещает свой CWD в корень пространства имен корневого монтирования.

Ничего из этого не происходит, когда я pivot_root(".", "oldroot"). Поведение также исчезает при размонтировании старого корня, либо через файловый дескриптор, umount -l /либо umount -l /proc/1/cwd.

Я также пробовал эту последовательность системных вызовов из пользовательской программы на языке C, поскольку документация pivot_rootтолько дает гарантии относительно текущего процесса (поэтому я делаю все в одном процессе). Поведение такое же, как и в многопроцессных шагах с использованием инструментов CLI, показанных выше.

Протестировано на ядре 5.3.

Что происходит, когда я бегу pivot_root(".", ".")?

решение1

pivot_root(new_root, put_old)перемещает старый корневой каталог вызывающего процесса (который должен быть корнем монтирования) на put_oldи помещает new_rootна его место. Затем он устанавливает текущий каталог и корень каждого процесса, который был установлен в старый корневой каталог, на new_root.

Итак, после того, как pivot_root(".", ".")новый корневой каталог смонтировал старый корневой каталог поверх себя.

Всякий раз, когда ..в противном случае он разрешался бы в каталог, в котором смонтирован другой каталог, он фактически разрешался бы в каталог, смонтированный наверху. Это соответствует историческому поведению Unix и Linux, где .., за исключением корневого каталога файловой системы, не было специальной обработки в обходе пути и было реализовано записью каталога, сохраненной на диске.

Это не экранирование пространства имен монтирования.

решение2

Похоже на настоящую ошибку...

Проверьте последнюю версию ядра вашего дистрибутива и сообщите о ней со всеми подробностями (приложите свою тестовую программу!).

Связанный контент