Comportamento estranho de pivot_root(".", ".") no namespace de montagem

Comportamento estranho de pivot_root(".", ".") no namespace de montagem

Estou tentando entender os containers e me deparei com um truque aparentemente encontrado pelos desenvolvedores do LXC, vejaeste runc PR: você pode chamar pivot_root(".", ".")o que evita a necessidade de um diretório para colocar a raiz antiga. No entanto, isso faz com que o namespace mount se comporte de maneira estranha:

unshare --user --map-root-user --mount bash -c "
mount --bind containerfs bindmountpoint
cd bindmountpoint
pivot_root . .
# this is fine:
ls -l /
# this is not fine:
ls -l /..
"

O pai de ., acessado via ./..ou /..ou /proc/<any>/cwd/..aponta para a raiz do namespace de montagem raiz (ainda não tentei aninhar)! Ele não aponta para o pai de containerfsnor bindmountpoint, mas realmente para a raiz do namespace de montagem raiz/externa.

Da mesma forma, quando tento nsenter --user --preserve-credentials --mount --target=<pid>, esse novo processo tem seu CWD colocado na raiz do namespace de montagem raiz.

Nada disso acontece quando eu pivot_root(".", "oldroot"). O comportamento também desaparece ao desmontar a raiz antiga, seja por meio de um descritor de arquivo umount -l /ou umount -l /proc/1/cwd.

Também tentei essa sequência de syscalls de um programa C customizado, pois a documentação do pivot_rootsó dá garantias sobre o processo atual (então faço tudo no mesmo processo). O comportamento é o mesmo das etapas de vários processos usando ferramentas CLI mostradas acima.

Testado em um kernel 5.3.

O que está acontecendo quando eu corro pivot_root(".", ".")?

Responder1

pivot_root(new_root, put_old)move o diretório raiz antigo do processo de chamada (que deve ser a raiz de uma montagem) para put_olde coloca new_rootem seu lugar. Em seguida, ele define o diretório atual e a raiz de cada processo que foi definido no diretório raiz antigo como new_root.

Então, depois que pivot_root(".", ".")o novo diretório raiz tiver o diretório raiz antigo montado sobre ele.

Sempre que ..for resolvido para o diretório que possui outro diretório montado, ele na verdade será resolvido para o diretório montado na parte superior. Isso corresponde ao comportamento histórico do Unix e do Linux, onde .., exceto no diretório raiz de um sistema de arquivos, não teve nenhum tratamento especial na travessia do caminho e foi implementado por uma entrada de diretório armazenada no disco.

Este não é um escape de namespace de montagem.

Responder2

Parece um bug genuíno...

Verifique o kernel mais recente da sua distribuição e relate-o com detalhes completos (anexe seu programa de teste!).

informação relacionada