Как мне монтировать приватный /proc внутри пространства имен внутри контейнера докера?

Мне нужно создать пространства имен внутри контейнера Docker. И как часть этого мне нужно будет смонтировать /proc частный для внутреннего пространства имен. Я понимаю, что мне придется запустить контейнер с определенными привилегиями, чтобы это произошло, но я бы предпочел включить минимальный набор.

Это работает:

$ sudo docker run --privileged --security-opt=seccomp=unconfined \
 -it fedora:rawhide /usr/bin/unshare -Ufmp -r \
 /bin/sh -c 'mount -t proc proc /proc'

Это не:

$ sudo docker run --cap-add=sys_admin --security-opt=seccomp=unconfined \
  -it fedora:rawhide /usr/bin/unshare -Ufmp -r \
   /bin/sh -c 'mount -t proc proc /proc'
mount: /proc: cannot mount proc read-only.

Итак, просто отключив фильтры seccomp и добавив CAP_SYS_ADMIN не достаточно Чего достаточно?

Обновление: Selinux является частью проблемы. Если вы отключите принудительное применение selinux по всему миру, это сработает. Но вы также можете отключить принудительное применение для конкретного контейнера с помощью --security-opt label:disable и это задокументировано в разделе конфигурации безопасности интерактивного руководства по Docker:

sudo docker run --cap-add=sys_admin --security-opt label:disable \
 -it fedora:rawhide /usr/bin/unshare -fmp /bin/sh -c \
 'mount --make-private / ; mount -t proc proc /proc'

Но это не удастся, если -U а также -r флаги добавляются обратно unshare, И, конечно же, добавив --privileged команда запуска Docker работает очень хорошо, даже с -U а также -r флаги.

В настоящее время я пытаюсь использовать средства трассировки ядра, чтобы выяснить, что именно дает мне EPERM. Это очень бесполезная ошибка.

1 ответ

Решение

Эта команда работает:

sudo docker run --cap-add=sys_admin --security-opt label:disable -it fedora:rawhide /bin/sh -c 'for dir in $(awk '"'"'/\/proc\// { print $5; }'"'"' /proc/1/mountinfo ); do umount "$dir"; done; /usr/bin/unshare -Ufmp -r /bin/sh -c '"'"'mount --make-private / ; mount -t proc proc /proc ; ls /proc'"'"

Я не разбил его на несколько строк, потому что цитирование действительно важно. По сути, он размонтирует целую кучу вещей в /proc перед запуском делиться и монтировать /proc в дочернем пространстве имен пользователя.

Docker монтирует кучу каталогов и файлов в /proc с его собственными каталогами, которые являются пустыми каталогами tmpfs и пустыми файлами. Различные файлы в /proc представляют значения, которые применимы ко всей системе. По факту, /proc/kcore позволил бы вам читать память ядра внутри контейнера, если бы вы были пользователем root, что, поскольку многие люди хотят верить, что контейнеры - это своего рода легкая виртуальная машина или что-то в этом роде, удивило бы многих людей.

Ядро в (начиная с версии 4.14 в любом случае) fs/namespace.c:mnt_already_visible проверяет, монтирует ли вы уже смонтированную файловую систему, и если в этой файловой системе есть вещи, смонтированные как дочерние файловые системы, и эти монтирования имеют флаг MNT_LOCKED, происходит сбой. Флаг MNT_LOCKED, кажется, применяется (я не выискивал, где это находится в ядре) ко всем монтируемым файлам всякий раз, когда вы создаете пространство имен пользователя, чтобы помешать вам демонтировать вещи в этом пространстве имен (потому что вы получаете привилегии "внутри" пространство имен пользователя) и сделать скрытые вещи видимыми снова.

Итак, команда, которую я разместил, использует скрипт awk для содержимого /proc/1/mountinfo вытащить все подкаталоги и файлы в /proc тот Докер сел и размонтировал их всех. Это делает /proc файловая система снова монтируется во вложенные пространства имен пользователя.

Другие вопросы по тегам