Linux - понимание пространства имен mount и клонирования CLONE_NEWNS

Я читаю mount и clone man page. Я хочу уточнить, как CLONE_NEWNS влияет на представление файловой системы для дочернего процесса.

(Иерархия файлов)

Давайте рассмотрим это дерево как иерархию каталогов. Давайте предположим, что 5 и 6 являются точками монтирования в родительском процессе. Я уточнил точки монтирования в другом вопросе .

Итак, я понимаю: 5 и 6 являются точками монтирования, означает, что команда mount использовалась ранее для "монтирования" файловых систем (иерархий каталогов) на 5 и 6 (это означает, что должны быть деревья каталогов под 5 и 6 также).

От mount справочной страницы:

 A mount namespace is the set of filesystem mounts that are visible to a process. 

Из clone справочной страницы:

Every process lives in a mount namespace.  The namespace of a process is the data 
(the set of mounts) describing the file hierarchy as seen by that process.  After 
a fork(2) or clone() where the CLONE_NEWNS flag is not set, the child lives in the 
same mount namespace as the parent.

Также:

After a clone() where the CLONE_NEWNS flag is set, the cloned child is started in a 
new mount namespace, initialized with a copy of the namespace of the parent.

Теперь, если я использую clone() с CLONE_NEWNS для создания дочернего процесса, означает ли это, что ребенок получит точную копию точек монтирования в дереве (5 и 6) и все еще сможет получить доступ к остальным исходного дерева? Это также означает, что ребенок мог установить 5 и 6 по своему желанию, не влияя на то, что смонтировано на 5 или 6 в пространстве имен для родительского процесса.

Если да, значит ли это также, что ребенок может монтировать/отключать другой каталог, чем 5 или 6, и влиять на видимость родительского процесса?

Спасибо.

Ответ 1

"Пространство имен монтирования" процесса - это всего лишь набор смонтированных файловых систем, которые он видит. Как только вы переходите от традиционной ситуации, когда одно глобальное пространство имен монтируется для пространств имен для каждого процесса, вы должны решить, что делать при создании дочернего процесса с помощью clone().

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

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

Должны ли изменения в пространстве имен монстров, созданных потомком, распространяться обратно на родителя?

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

В равной степени ясно, что это необходимое распространение должно быть подавлено, в противном случае мы никогда не сможем создать дочерний процесс, чье пространство имен монстров отличается от его родительского элемента, и мы снова имеем одно глобальное пространство имен имен (файловая система, t24 > ).

Таким образом, мы должны решить, при создании дочернего процесса с clone(), получает ли дочерний процесс свою собственную копию данных о смонтированных файловых системах от родителя, которые он может изменить, не затрагивая родителя, или получает указатель на те же структуры данных, что и родительский элемент, который он может изменить (необходимо, чтобы изменения распространялись обратно, как при запуске mount из оболочки).

Если флаг CLONE_NEWNS передается в clone(), дочерний элемент получает копию данных родительской смоделированной файловой системы, которые он может изменить, не затрагивая пространство имен родительского монстра. В противном случае он получает указатель на структуры данных родительского монтирования, где изменения, сделанные дочерним элементом, будут рассматриваться родителем (поэтому сама команда mount может работать).

Теперь, если я использую клон с CLONE_NEWNS для создания дочернего процесса, означает ли это, что ребенок получит точную копию точек монтирования в дереве (5 и 6) и все еще сможет получить доступ к остальной части исходного дерева

Да. Он видит то же самое дерево, что и его родительский после вызова clone().

Это также означает, что ребенок может установить 5 и 6 по своему желанию, не влияя на то, что смонтировано на 5 или 6 в пространстве имен родительского процесса.

Да. Поскольку вы использовали CLONE_NEWNS, ребенок может размонтировать одно устройство с 5 и подключить к нему другое устройство, и только он (и его дети) мог видеть изменения. В этом случае ни один другой процесс не может видеть изменения, внесенные ребенком.

Если да, значит ли это также, что ребенок может монтировать/отключать другой каталог, чем 5 или 6, и влиять на видимость родительского процесса?

Нет. Если вы использовали CLONE_NEWNS, изменения, внесенные в дочерний элемент, не могут распространяться обратно на родителя.

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

Ответ 2

У меня недостаточно очков репутации, чтобы добавить комментарий, вместо этого добавив этот комментарий в качестве ответа. Это просто добавление к ответу Эммета.

AFAICU. Если процесс создан с установленным флагом CLONE_NEWNS, он может монтировать только те файловые системы, у которых установлен флаг FS_USERNS_MOUNT. И почти все дисковые файловые системы не устанавливают этот флаг (из-за соображений безопасности). В do_new_mount есть эта проверка:

        if (user_ns != &init_user_ns) {
            if (!(type->fs_flags & FS_USERNS_MOUNT)) {
                    put_filesystem(type);
                    return -EPERM;
            }

Пожалуйста, поправьте меня, если я ошибаюсь