Como eu monto um private / proc dentro de um namespace dentro de um contêiner docker?

1

Eu preciso criar namespaces dentro de um contêiner do Docker. E como parte disso, precisarei montar um /proc private no namespace interno. Percebo que terei que executar o contêiner com certos privilégios para que isso aconteça, mas eu preferiria ativar o conjunto mais mínimo.

Isso funciona:

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

Isso não acontece:

$ 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.

Portanto, desativar os filtros seccomp e adicionar CAP_SYS_ADMIN não é suficiente. O que é suficiente?

Atualização: O Selinux faz parte do problema. Se você desativar a aplicação do selinux globalmente, isso funcionará. Mas você também pode desativar a aplicação de um determinado contêiner com --security-opt label:disable , e isso está documentado na seção de configuração de segurança do manual on-line do 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'

Mas isso falhará se os sinalizadores -U e -r forem adicionados novamente a unshare . E, claro, adicionar --privileged ao comando docker run funciona muito bem, mesmo com os sinalizadores -U e -r .

Atualmente estou tentando usar o material de rastreamento do kernel para descobrir o que, exatamente, está me dando um EPERM. É um erro muito inespecífico e não específico.

    
por Omnifarious 14.02.2018 / 22:48

1 resposta

1

Este comando funciona:

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'"'"

Eu não o dividi em várias linhas porque a citação é realmente importante. Basicamente, ele desmonta um monte de coisas em /proc antes de executar o compartilhamento não compartilhado e montar /proc no namespace do usuário filho.

O Docker é montado sobre vários diretórios e arquivos em /proc com seus próprios diretórios que são diretórios tmpfs vazios e arquivos nulos. Vários arquivos em /proc representam valores aplicáveis a todo o sistema. De fato, /proc/kcore permitiria que você lesse a memória do kernel dentro do container se você fosse root, o que, uma vez que muitas pessoas querem acreditar que contêineres são algum tipo de VM leve ou algo assim, surpreenderia muita gente. / p>

O kernel em (a partir da versão 4.14) fs/namespace.c:mnt_already_visible verifica se você está montando um sistema de arquivos já montado, e se esse sistema de arquivos tiver coisas montadas como sistemas filhos e essas montagens tiverem o sinalizador MNT_LOCKED, ele falhará. O sinalizador MNT_LOCKED parece ser aplicado (eu não procurei onde este está no kernel) para todas as montagens sempre que você cria um namespace de usuário para evitar que você desmonte coisas nesse namespace (porque você obtém privilégios 'dentro' do espaço de nomes do usuário) e tornar o material oculto visível novamente.

Portanto, o comando que postei usa um script awk no conteúdo de /proc/1/mountinfo para extrair todos os subdiretórios e arquivos em /proc que o Docker montou e desmonta todos eles. Isso torna o sistema de arquivos /proc montável em namespaces de usuário aninhados novamente.

    
por 16.02.2018 / 00:51