chroot до pivot_root вызывает ошибку занятости

# unshare -m # mount --bind / /mnt # cd /mnt # chroot . # pivot_root . mnt pivot_root: failed to change root from `.' to `mnt': Device or resource busy 

Почему это не удается? Я следовал инструкциям от man 2 pivot_mount .

pivot_root () может изменить или не изменить текущий корневой каталог и текущий рабочий каталог любых процессов или streamов, которые используют старый корневой каталог. Вызывающая функция pivot_root () должна убедиться, что процессы с корневым или текущим рабочим каталогом в старом корневом каталоге работают правильно в любом случае. Простой способ убедиться в этом – изменить их корневой и текущий рабочий каталог на new_root перед вызовом pivot_root ().

Я не вижу, как это соответствует документированной ошибке EBUSY.

ОШИБКИ

pivot_root () может возвратить (по ошибке) любую из ошибок, возвращенных stat (2). Кроме того, он может вернуть:

EBUSY new_root или put_old находятся в текущей корневой файловой системе, или файловая система уже смонтирована в put_old.

Эта часть руководства вводит в заблуждение. Как правило, вы хотите другой порядок, как описано в man 8 pivot_root .

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

Это, кажется, еще одна тонкая деталь с pivot_root . Хотя цель pivot_root состоит в том, чтобы переставить пространство имен монтирования, код ядра, кажется, говорит, что корневая файловая система, которую он перемещает, определяется корнем для каждого процесса, что и устанавливает chroot .

В результате мы сталкиваемся с ошибкой «new_root или put_old находятся в текущей корневой файловой системе».

Эта тонкая деталь pivot_root необходима для того, чтобы он вообще работал на современном Linux. Если он определен для работы с корневым монтированием пространства имен монтирования, он попытается переместить специальную файловую систему rootfs которую вы обычно не видите . Но это недопустимо, потому что rootfs всегда должен быть корневым монтированием пространства имен .


Мы можем подтвердить, что pivot_root работает таким образом, продолжив пример следующим образом.

 # unshare -m # mount --bind / /mnt # cd /mnt # chroot /mnt # pivot_root . mnt pivot_root: failed to change root from `.' to `mnt': Device or resource busy # exit # leave chroot # mount --bind . mnt # cd mnt # mount --bind /proc proc # findmnt | grep mnt └─/mnt /dev/mapper/alan_dell_2016-fedora ext4 rw,relatime,seclabel └─/mnt /dev/mapper/alan_dell_2016-fedora ext4 rw,relatime,seclabel └─/mnt/proc proc proc rw,nosuid,nodev,noexec,relatime # chroot /mnt # re-enter chroot # cd /mnt # pivot_root . mnt # this one works # exit # leave chroot # findmnt | grep mnt └─/mnt /dev/mapper/alan_dell_2016-fedora ext4 rw,relatime,seclabel ├─/mnt/mnt /dev/mapper/alan_dell_2016-fedora ext4 rw,relatime,seclabel └─/mnt/proc /dev/mapper/alan_dell_2016-fedora[/proc] ext4 rw,relatime,seclabel 

Второй вызов pivot_root работает. Но это не оказало никакого влияния на корень пространства имен mount. Если смотреть снаружи chroot , он поменял местами /mnt и /mnt/mnt .