MOUNT_NAMESPACES(7) Руководство программиста Linux MOUNT_NAMESPACES(7)

ИМЯ

mount_namespaces - обзор пространств имён монтирования в Linux

ОПИСАНИЕ

Обзор пространств имён смотрите в namespaces(7).

Пространства имён монтирования позволяют изолировать список точек монтирования, видимый процессами в каждом экземпляре пространства имён. То есть, процессы в каждом из экземпляров пространства имён монтирования будут видеть разные иерархии в одном и том же каталоге.

Данные файлов /proc/[pid]/mounts, /proc/[pid]/mountinfo и /proc/[pid]/mountstats (описаны в proc(5)) соответствуют пространству имён монтирования, в котором расположен процесс с PID [pid] (для всех процессов, которые расположены в одном пространстве имён монтирования, данные в этих файлах одинаковы).

Когда процесс создаёт новое пространство имён монтирования с помощью clone(2) или unshare(2) с флагом CLONE_NEWNS список точек монтирования для нового пространства имён представляет собой копию списка точек монтирования вызывающего. Последующие изменения списка точек монтирования (mount(2) и umount(2)) в любом пространстве имён монтирования не влияют (по умолчанию) на список точек монтирования, видимый из другого пространства имён (но смотрите далее описание общих поддеревьев).

Ограничения у пространств имён монтирования

Отметим следующие моменты относительно пространств имён монтирования:

  • Владельцем пространства имён монтирования является владелец пользовательского пространство имён. Пространство имён монтирования, чей владелец пользовательского пространства имён отличается от владельца пользовательского пространства имён родительского пространства имён монтирования, считается менее привилегированным пространством имён монтирования.
  • При создании менее привилегированного пространства имён монтирования количество общих точек монтирования сокращаются до списка подчинённых точек монтирования (про общие и подчинённые точки монтирования смотрите далее). Это гарантирует, что отображения, выполняемые в менее привилегированном пространстве имён монтирования, не распространятся в более привилегированные пространства имён монтирования.
  • Точки монтирования, которые появились как единый блок из более привилегированного монтирования, объединяются и не могут быть разделены в менее привилегированном пространстве имён монтирования (операция unshare(2) CLONE_NEWNS переносит все точки монтирования из исходного пространства имён монтирования единым блоком и рекурсивные монтирования, которые передаются в нескольких пространствах имён монтирования, также единым блоком).
  • Значения флагов MS_RDONLY, MS_NOSUID, MS_NOEXEC у mount(2) и флагов «atime» (MS_NOATIME, MS_NODIRATIME, MS_RELATIME) блокируются при передаче из более привилегированного в менее привилегированное пространство имён монтирования, и не могут быть изменены в менее привилегированном пространстве имён монтирования.
  • Файл или каталог, являющийся точкой монтирования в одном пространстве имён, и не являющийся в другом, может быть переименован, отсоединён (unlinked) или удалён (rmdir(2)) в пространстве имён монтирования, в котором он не является точкой монтирования (выполняются обычные проверки прав доступа).
Раньше, попытка переименовать, отсоединить или удалить файл или каталог, который являлся точкой монтирования в другом пространстве имён монтирования, приводила к ошибке EBUSY. Такое поведение вызывало технические проблемы в работе (например, NFS) и позволяло выполнять атаку отказа в обслуживании более привилегированных пользователей (т. е., не давало обновлять отдельные файлы посредством монтирования поверх их).

ОБЩИЕ ПОДДЕРЕВЬЯ

После завершения реализации пространств имён монтирования опыт использования показал, что полученная изоляция, в некоторых случаях, слишком велика. Например, чтобы только что смонтированный оптический диск сделать доступным в во всех пространствах имён, требуется операция монтирования в каждом пространстве имён. Для этого случаях и других в Linux 2.6.15 были добавлены общие поддеревья. Это свойство предоставляет автоматическое, управляемое распространение событий монтирования и размонтирования в пространствах имён (или, точнее, между членами равноправной группы, которые обмениваются событиями между собой).

Каждая точка монтирования помечается (в mount(2)) одним из следующих типов распространения:

События такой точки монтирования являются общими с остальными членами равноправной группы. События монтирования и размонтирования этой точки сразу же распространяются на другие точки монтирования, являющиеся членами равноправной группы. То есть монтирование или размонтирование автоматически происходит и у всех остальных точек монтирования в равноправной группе. И наоборот, события монтирования и размонтирования, возникшие у точек монтирования равноправной группы, будут распространены и на эту точку монтирования.
Данная точка монтирования индивидуальна; у неё нет равноправной группы. События монтирования и размонтирования не распространяются от этой точки и на эту точку.
События монтирования и размонтирования распространяются на эту точку монтирования из (главной) общей равноправной группы. События монтирования и размонтирования этой точки не распространяются на членов группы.
Заметим, что точка монтирования может быть подчинённой одной равноправной группе и в тоже время может распространять события в другую группу, где она является членом (точнее, одна равноправная группа может быть подчинённой другой равноправной группе).
Данный тип подобен индивидуальной точке монтирования, но дополнительно такая точка монтирования не может быть привязана (bind). Попытка привязать эту точку монтирования (mount(2) с флагом MS_BIND) завершится ошибкой.
При рекурсивной привязке (mount(2) с флагами MS_BIND и MS_REC) поддерева каталога все привязки внутри поддерева автоматически удаляются (т. е., не копируются) при копировании этого поддерева для создания целевого поддерева.

Описание типа распространения, назначаемого на новое монтирование, смотрите в ЗАМЕЧАНИЯХ.

Тип распространения имеется у каждой точки монтирования; некоторые точки монтирования могут быть помечены как общие (каждая общая точка монтирования является членом определённой равноправной группы), а некоторые как индивидуальные (или подчинённые или непривязываемые).

Заметим, что тип распространения монтирования определяет, будет ли монтирование или размонтирование распространяться точки монтирования, находящиеся на одну ступень ниже точки, где возникло событие. То есть, тип распространения не влияет на распространение событий для внуков и в дальнейшем удаляемых потомков точки монтирования. Это случается, если сама точка монтирования размонтируется из-за действия типа распространения который, в сущности, влияние родительской точки монтирования.

Члены добавляются в равноправную группу, если точка монтирования помечается как общая, или:

  • точка монтирования копируется при создании нового пространства имён монтирования
  • создаётся новая привязка из точки монтирования

В обоих случаях новая точка монтирования присоединяется к равноправной группе, в которую входит существующая точка монтирования.

Новая равноправная группа также создаётся, если дочерняя точка монтирования создана под существующей точкой монтирования, помеченной как общая. В этом случае, новая дочерняя точка монтирования также помечается как общая и получаемая равноправная группа состоит из всех точек монтирования, которые дублируются в равноправных группах родительской точки монтирования.

Точка монтирования перестаёт быть членом равноправной группы, когда происходит её явное размонтирование или неявное из-за удаления пространства имён монтирования (из-за отсутствия участвующих процессов).

Тип распространения точек монтирования в пространстве имён монтирования может узнать через «необязательные поля» в файле /proc/[pid]/mountinfo (описание файла смотрите в proc(5)). В необязательных полях этого файла могут появляться следующие метки:

Эта точка монтирования является общей в равноправной группе X. Каждая равноправная группа имеет автоматически генерируемый ядром уникальный идентификатор, и у всех точек монтирования одной равноправной группы здесь будет одинаковый идентификатор (эти идентификаторы начинаются с 1 и могут повторно использоваться, когда в равноправной группе не останется членов).
Эта точка монтирования является подчинённой общей равноправной группе X.
Эта точка монтирования является подчинённой и принимает события от общей равноправной группы X. Данная метка всегда появляется вместе с меткой master:X. Здесь X это ближайшая главенствующая равноправная группа из корневого каталога процесса. Если X является непосредственным владельцем точки монтирования, или в том же корне нет ближайшей главенствующей равноправной группы, то существует только поле master:X, и поле propagate_from:X отсутствует. Подробности смотрите ниже.
Точка монтирования является непривязываемой.

Если нет ни одной из вышеперечисленных меток, то точка монтирования является индивидуальной.

Пример MS_SHARED и MS_PRIVATE

Предположим, что на терминале в первоначальном пространстве имён монтирования мы помечаем одну точку монтирования как общую, а другую — как индивидуальную, и затем смотрим точки монтирования в /proc/self/mountinfo:

sh1# mount --make-shared /mntS
sh1# mount --make-private /mntP
sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
77 61 8:17 / /mntS rw,relatime shared:1
83 61 8:15 / /mntP rw,relatime

Из вывода /proc/self/mountinfo мы видим, что /mntS является общей точкой монтирования в равноправной группе 1, и что /mntP не имеет необязательных меток, то есть это индивидуальная точка монтирования. Первые два поля в каждой записи этого файла содержат уникальный идентификатор этой точки монтирования и идентификатор точки монтирования родительской точки монтирования. Далее в файле мы видим, что родительская точка монтирования /mntS и /mntP является корневым каталогом, /, которая смонтирована как индивидуальная:

sh1# cat /proc/self/mountinfo | awk '$1 == 61' | sed 's/ - .*//'
61 0 8:2 / / rw,relatime

На втором терминале мы создаём новое пространство имён монтирования, в котором запускаем вторую оболочку, и смотрим точки монтирования:

$ PS1='sh2# ' sudo unshare -m --propagation unchanged sh
sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
222 145 8:17 / /mntS rw,relatime shared:1
225 145 8:15 / /mntP rw,relatime

Новое пространство имён монтирования получает копию точек монтирования из начального пространства имён монтирования. Эти новые точки монтирования имеют тот же тип распространения, но другие уникальные идентификаторы монтирования (при создании нового пространства имён монтирования передача параметра --propagation unchanged программе unshare(1) не даёт помечать все точки монтирования как индивидуальные (что делается по умолчанию)).

Далее на втором терминале мы создаём подмонтирования в каталоге /mntS и /mntP и смотрим что получилось:

sh2# mkdir /mntS/a
sh2# mount /dev/sdb6 /mntS/a
sh2# mkdir /mntP/b
sh2# mount /dev/sdb7 /mntP/b
sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
222 145 8:17 / /mntS rw,relatime shared:1
225 145 8:15 / /mntP rw,relatime
178 222 8:22 / /mntS/a rw,relatime shared:2
230 225 8:23 / /mntP/b rw,relatime

Из показанного выше мы видим, что /mntS/a была создана как общая (унаследовала от родительской точки монтирования), а /mntP/b — как индивидуальная точка монтирования.

Если вернуться на первый терминал и и ещё раз посмотреть параметры, то можно увидеть, что новая точка монтирования, созданная в общей точке монтирования /mntS, передалась в свою равноправную группу монтирования (в начальном пространстве имён монтирования), а новая точка монтирования, созданная в индивидуальной точке монтирования /mntP, нет:

sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
77 61 8:17 / /mntS rw,relatime shared:1
83 61 8:15 / /mntP rw,relatime
179 77 8:22 / /mntS/a rw,relatime shared:2

Пример MS_SLAVE

Создание подчинённой точки монтирования позволяет ей принимать распространяемые события монтирования и размонтирования из главной общей равноправной группы, но запрещает распространять события в эту главную группу. Это полезно, если требуется, скажем, принимать событие монтирования оптического диска в главной общей равноправной группе (в другом пространстве имён монтирования), но не нужно, чтобы события монтирования и размонтирования в подчинённой точке монтирования передавались в другие пространства имён.

Для демонстрации следствия подчинённости сначала создадим две общие точки монтирования в начальном пространстве имён монтирования:

sh1# mount --make-shared /mntX
sh1# mount --make-shared /mntY
sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
132 83 8:23 / /mntX rw,relatime shared:1
133 83 8:22 / /mntY rw,relatime shared:2

На втором терминале создадим новое пространство имён монтирования и посмотрим точки монтирования:

sh2# unshare -m --propagation unchanged sh
sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
168 167 8:23 / /mntX rw,relatime shared:1
169 167 8:22 / /mntY rw,relatime shared:2

Далее в новом пространстве имён монтирования пометим одну из точек монтирования как подчинённую:

sh2# mount --make-slave /mntY
sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
168 167 8:23 / /mntX rw,relatime shared:1
169 167 8:22 / /mntY rw,relatime master:2

Из показанного выше видно, что /mntY теперь подчинённая точка монтирования, которая принимать распространяемые события от общей равноправной группы с ID 2.

Далее в новом пространстве имён создадим подмонтирования в /mntX и /mntY:

sh2# mkdir /mntX/a
sh2# mount /dev/sda3 /mntX/a
sh2# mkdir /mntY/b
sh2# mount /dev/sda5 /mntY/b

Если посмотреть состояние точек монтирования в новом пространстве имён монтирования можно увидеть, что /mntX/a создана как новая общая точка монтирования (наследует «общность» от родительской точки монтирования), а /mntY/b создана как индивидуальная точка монтирования:

sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
168 167 8:23 / /mntX rw,relatime shared:1
169 167 8:22 / /mntY rw,relatime master:2
173 168 8:3 / /mntX/a rw,relatime shared:3
175 169 8:5 / /mntY/b rw,relatime

Если вернуться на первый терминал (в начальное пространство имён монтирования), то можно увидеть, что точка монтирования /mntX/a передалась в свою равноправную группу (общую с /mntX), а точка монтирования /mntY/b нет:

sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
132 83 8:23 / /mntX rw,relatime shared:1
133 83 8:22 / /mntY rw,relatime shared:2
174 132 8:3 / /mntX/a rw,relatime shared:3

Теперь создадим новую точку монтирования в /mntY в первом терминале:

sh1# mkdir /mntY/c
sh1# mount /dev/sda1 /mntY/c
sh1# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
132 83 8:23 / /mntX rw,relatime shared:1
133 83 8:22 / /mntY rw,relatime shared:2
174 132 8:3 / /mntX/a rw,relatime shared:3
178 133 8:1 / /mntY/c rw,relatime shared:4

Если посмотреть точки монтирования во втором пространстве имён монтирования, то можно увидеть, что на этот раз новая точка монтирования передалась в подчинённую точку монтирования и что эта новая точка монтирования сама является подчинённой (равноправной группе 4):

sh2# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
168 167 8:23 / /mntX rw,relatime shared:1
169 167 8:22 / /mntY rw,relatime master:2
173 168 8:3 / /mntX/a rw,relatime shared:3
175 169 8:5 / /mntY/b rw,relatime
179 169 8:1 / /mntY/c rw,relatime master:4

Пример MS_UNBINDABLE

Одним из основных назначений непривязываемых точек монтирования является решение проблемы «взрыва точек монтирования» — повторяющееся выполнение привязки точки монтирования поддерева верхнего уровня в точках монтирования нижнего уровня. Эта проблема показана в сеансе далее.

Предположим, что имеется система с следующими точками монтирования:

# mount | awk '{print $1, $2, $3}'
/dev/sda1 on /
/dev/sdb6 on /mntX
/dev/sdb7 on /mntY

Предположим, что нужно рекурсивно привязать точки монтирования корневого каталога в нескольких пользовательских домашних каталогах. Сделаем это для первого пользователя и посмотрим точки монтирования:

# mount --rbind / /home/cecilia/
# mount | awk '{print $1, $2, $3}'
/dev/sda1 on /
/dev/sdb6 on /mntX
/dev/sdb7 on /mntY
/dev/sda1 on /home/cecilia
/dev/sdb6 on /home/cecilia/mntX
/dev/sdb7 on /home/cecilia/mntY

Повторяя эту операцию для второго пользователя сталкиваемся с проблемой взрывного роста:

# mount --rbind / /home/henry
# mount | awk '{print $1, $2, $3}'
/dev/sda1 on /
/dev/sdb6 on /mntX
/dev/sdb7 on /mntY
/dev/sda1 on /home/cecilia
/dev/sdb6 on /home/cecilia/mntX
/dev/sdb7 on /home/cecilia/mntY
/dev/sda1 on /home/henry
/dev/sdb6 on /home/henry/mntX
/dev/sdb7 on /home/henry/mntY
/dev/sda1 on /home/henry/home/cecilia
/dev/sdb6 on /home/henry/home/cecilia/mntX
/dev/sdb7 on /home/henry/home/cecilia/mntY

В /home/henry рекурсивно добавились не только точки монтирования /mntX и /mntY, но и рекурсивные точки монтирования этих каталогов, смонтированных в /home/cecilia, который мы создали на предыдущем шаге. Далее повторяя процесс для третьего пользователя, станет очевидно, что взрывной рост происходит экспоненциально:

# mount --rbind / /home/otto
# mount | awk '{print $1, $2, $3}'
/dev/sda1 on /
/dev/sdb6 on /mntX
/dev/sdb7 on /mntY
/dev/sda1 on /home/cecilia
/dev/sdb6 on /home/cecilia/mntX
/dev/sdb7 on /home/cecilia/mntY
/dev/sda1 on /home/henry
/dev/sdb6 on /home/henry/mntX
/dev/sdb7 on /home/henry/mntY
/dev/sda1 on /home/henry/home/cecilia
/dev/sdb6 on /home/henry/home/cecilia/mntX
/dev/sdb7 on /home/henry/home/cecilia/mntY
/dev/sda1 on /home/otto
/dev/sdb6 on /home/otto/mntX
/dev/sdb7 on /home/otto/mntY
/dev/sda1 on /home/otto/home/cecilia
/dev/sdb6 on /home/otto/home/cecilia/mntX
/dev/sdb7 on /home/otto/home/cecilia/mntY
/dev/sda1 on /home/otto/home/henry
/dev/sdb6 on /home/otto/home/henry/mntX
/dev/sdb7 on /home/otto/home/henry/mntY
/dev/sda1 on /home/otto/home/henry/home/cecilia
/dev/sdb6 on /home/otto/home/henry/home/cecilia/mntX
/dev/sdb7 on /home/otto/home/henry/home/cecilia/mntY

Проблемы взрывного роста монтирования в показанном сценарии можно избежать, если делать каждое новое монтирование непривязываемым. В этом случае рекурсивное монтирование корневого каталоге не копирует непривязываемые точки монтирования. Сделаем такое монтирование для первого пользователя:

# mount --rbind --make-unbindable / /home/cecilia

Перед тем как продолжить, посмотрим, что непривязываемые точки монтирования действительно нельзя привязать:

# mkdir /mntZ
# mount --bind /home/cecilia /mntZ
mount: wrong fs type, bad option, bad superblock on /home/cecilia,

       missing codepage or helper program, or other error

       В некоторых случаях полезная информация может быть

       найдена в syslog - попробуйте dmesg | tail или что-то

       в этом роде.

Теперь создадим непривязываемое рекурсивное монтирования для остальных пользователей:

# mount --rbind --make-unbindable / /home/henry
# mount --rbind --make-unbindable / /home/otto

Если посмотреть список точек монтирования, то можно увидеть, что взрывного роста не произошло, так как непривязываемые точки монтирования не скопировались в каждый пользовательский каталог:

# mount | awk '{print $1, $2, $3}'
/dev/sda1 on /
/dev/sdb6 on /mntX
/dev/sdb7 on /mntY
/dev/sda1 on /home/cecilia
/dev/sdb6 on /home/cecilia/mntX
/dev/sdb7 on /home/cecilia/mntY
/dev/sda1 on /home/henry
/dev/sdb6 on /home/henry/mntX
/dev/sdb7 on /home/henry/mntY
/dev/sda1 on /home/otto
/dev/sdb6 on /home/otto/mntX
/dev/sdb7 on /home/otto/mntY

Переходы типов распространения

В следующей таблице показано как влияет применение нового типа распространения (т. е., mount --make-xxxx) на текущий тип распространения точки монтирования. Строки соответствуют существующим типам распространения, а столбцы — заданию нового типа распространения. Из-за нехватки места «индивидуальная» тип сокращён до «инд», а «непривязываемая» до «неприв».

сделать-общим сделать-подчинён сделать-инд сделать-неприв
общий общий общий/инд [1] инд неприв
подчинён подчинён+общий подчинён [2] инд неприв
подчинён+общий подчинён+общий подчинён инд неприв
инд общий инд [2] инд неприв
неприв общий неприв [2] инд неприв

Замечания к таблице:

[1]
Если общая точка монтирования смонтирована только в её равноправной группе, то изменение её типа на подчинённый автоматически делает её индивидуальной.
[2]
Подчинение не общей точки монтирования не влияет на монтирование.

Семантика привязывания (MS_BIND)

Предположим, что выполняется следующая команда:

mount --bind A/a B/b

Здесь A — исходная точка монтирования, B — целевая точка монтирования, a — подкаталог в точке монтирования A и b — подкаталог в точке монтирования B. Тип распространения получаемой точки, B/b, зависит от типов распространения точек монтирования A и B, и рассчитывается по следующей таблице:

исход(A)
общий инд подчинён неприв
цель(B) общий | общий общий подчинён+общий некорректно
не_общий | общий инд подчинён некорректно

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

Дополнительную информацию смотрите в файле Documentation/filesystems/sharedsubtree.txt дерева исходного кода ядра.

Семантика перемещения (MS_MOVE)

Предположим, что выполняется следующая команда:

mount --move A B/b

Здесь A — исходная точка монтирования, B — целевая точка монтирования и b — подкаталог в точке монтирования B. Тип распространения получаемой точки, B/b, зависит от типов распространения точек монтирования A и B, и рассчитывается по следующей таблице:

исход(A)
общий инд подчинён неприв
цель(B) общий | общий общий подчинён+общий некорректно
не_общий | общий инд подчинён неприв

Замечание: перемещение точки монтирования, располагающейся ниже общей точки, некорректно.

Дополнительную информацию смотрите в файле Documentation/filesystems/sharedsubtree.txt дерева исходного кода ядра.

Семантики монтирования

Предположим, что для создания точки монтирования используется следующая команда:

mount устройство B/b

Здесь B — целевая точка монтирования и b — подкаталог в точке монтирования B. Тип распространения получаемой точки, B/b, получается таким же как при привязывании, где тип распространения исходной точки монтирования всегда равен индивидуальному.

Семантики размонтирования

Предположим, что для размонтирования точки используется следующая команда:

unmount A

Здесь A точка монтирования на B/b, где B — родительская точка монтирования и b — подкаталог в точке монтирования B. Если B имеет общий тип распространения, то все последние монтирования в b, получающие события от точки монтирования B и не имеющие подмонтирований внутри, будут размонтированы.

Метка /proc/[pid]/mountinfo propagate_from

Метка propagate_from:X появляется в необязательных полях записи /proc/[pid]/mountinfo в случаях, когда процесс не может видеть непосредственного мастера (т. е., путь к мастеру недоступен из корневого каталога файловой системы) и поэтому не может определить цепочку распространения между точками монтирования, которые он может видеть.

В следующем примере сначала создаётся двусвязная цепочка мастер-подчинённый между точками монтирования /mnt, /tmp/etc и /mnt/tmp/etc. Затем используется команда chroot(1), чтобы сделать точку монтирования /tmp/etc недоступной из корневого каталога, что создаёт ситуацию, где мастер для /mnt/tmp/etc недоступен из (нового) корневого каталога процесса.

Сначала привяжем корневой каталог в /mnt, а затем привяжем /proc в /mnt/proc, чтобы после этого в правильном месте chroot-окружения для chroot(1) осталась доступной файловая система proc(5).

# mkdir -p /mnt/proc
# mount --bind / /mnt
# mount --bind /proc /mnt/proc

Теперь убедимся, что точка монтирования /mnt является общей в новой равноправной группе (без членов):

# mount --make-private /mnt  # Изолировать от любой предыдущей группы
# mount --make-shared /mnt
# cat /proc/self/mountinfo | grep '/mnt' | sed 's/ - .*//'
239 61 8:2 / /mnt ... shared:102
248 239 0:4 / /mnt/proc ... shared:5

Теперь привяжем /mnt/etc к /tmp/etc:

# mkdir -p /tmp/etc
# mount --bind /mnt/etc /tmp/etc
# cat /proc/self/mountinfo | egrep '/mnt|/tmp/' | sed 's/ - .*//'
239 61 8:2 / /mnt ... shared:102
248 239 0:4 / /mnt/proc ... shared:5
267 40 8:2 /etc /tmp/etc ... shared:102

Первоначально, эти две точки монтирования были в одной равноправной группе, но мы сделали /tmp/etc подчинённой /mnt/etc, а затем сделали /tmp/etc общей, так чтобы она могла распространять события следующему подчинённому в цепочке:

# mount --make-slave /tmp/etc
# mount --make-shared /tmp/etc
# cat /proc/self/mountinfo | egrep '/mnt|/tmp/' | sed 's/ - .*//'
239 61 8:2 / /mnt ... shared:102
248 239 0:4 / /mnt/proc ... shared:5
267 40 8:2 /etc /tmp/etc ... shared:105 master:102

Затем мы привязали /tmp/etc в /mnt/tmp/etc. Опять же, две точки монтирования первоначально были в одной равноправной группе, но позднее мы сделали /mnt/tmp/etc подчинённой /tmp/etc:

# mkdir -p /mnt/tmp/etc
# mount --bind /tmp/etc /mnt/tmp/etc
# mount --make-slave /mnt/tmp/etc
# cat /proc/self/mountinfo | egrep '/mnt|/tmp/' | sed 's/ - .*//'
239 61 8:2 / /mnt ... shared:102
248 239 0:4 / /mnt/proc ... shared:5
267 40 8:2 /etc /tmp/etc ... shared:105 master:102
273 239 8:2 /etc /mnt/tmp/etc ... master:105

Из показанного выше можно видеть, что /mnt является главной для подчинённой /tmp/etc, которая, в свою очередь, является главной для подчинённой /mnt/tmp/etc.

Теперь выполним chroot(1) в каталог /mnt, который делает точку монтирования с ID 267 недоступной из (нового корневого каталога:

# chroot /mnt

Если мы проверим состояние точек монтирования внутри окружения chroot, то увидим следующее:

# cat /proc/self/mountinfo | sed 's/ - .*//'
239 61 8:2 / / ... shared:102
248 239 0:4 / /proc ... shared:5
273 239 8:2 /etc /tmp/etc ... master:105 propagate_from:102

Здесь мы видим, что точка монтирования с ID 273 является подчинённой для главной, которая входит в равноправную группу 105. Точка монтирования этой главной недоступна и поэтому появилась метка propagate_from, показывающая, что идентификатор ближайшей ведущей равноправной группы (т. е., ближайшая достижимая точка монтирования в подчинённой цепи) равен 102 (соответствует точке монтирования /mnt до выполнения chroot(1)).

ВЕРСИИ

Пространство имён монтирования впервые появилось в Linux 2.4.19.

СООТВЕТСТВИЕ СТАНДАРТАМ

Пространства имён есть только в Linux.

ЗАМЕЧАНИЯ

Тип распространения, назначаемый новой точке монтирования, зависит от типа распространения родительского каталога. Если точка монтирования имеет родителя (т. е., является не корневой точкой монтирования) и тип распространения родителя — MS_SHARED, то тип распространения новой точки монтирования будет также MS_SHARED. В противном случае типом новой точки монтирования будет MS_PRIVATE. Но смотрите, также ЗАМЕЧАНИЯ.

Несмотря на то, что тип распространения по умолчанию для новой точки монтирования во многих случаях равен MS_PRIVATE, обычно, тип MS_SHARED полезнее. По этой причине, при запуске системы systemd(1) автоматически перемонтирует все точки монтирования как MS_SHARED. Таким образом, в современных системах типом распространения по умолчанию практически является MS_SHARED.

При создании пространства имён монтирования с помощью unshare(1) чаще всего требуется создать полную изоляцию точек монтирования в новом пространстве имён, и unshare(1) (начиная с util-linux версии 2.27) отменяет изменения systemd(1), делая все точки монтирования индивидуальными в новом пространстве имён. То есть unshare(1) в новом пространстве имён монтирования выполняет эквивалент следующего:

mount --make-rprivate /

Чтобы этого не происходило в unshare(1) можно использовать параметр --propagation unchanged.

Описание типов распространения при перемещении точек монтирования (MS_MOVE) и создании привязок монтирования (MS_BIND) смотрите в Documentation/filesystems/sharedsubtree.txt.

СМОТРИТЕ ТАКЖЕ

unshare(1), clone(2), mount(2), setns(2), umount(2), unshare(2), proc(5), namespaces(7), user_namespaces(7), findmnt(8)

Файл Documentation/filesystems/sharedsubtree.txt в дереве исходного кода ядра Linux.

2018-04-30 Linux