Quando um processo filho é criado com clone
com o sinalizador CLONE_NEWNS
, o processo filho recebe seu próprio namespace de montagem. As operações de montagem ( mount
, umount
, mount --bind
, etc.) no namespace filho têm apenas um efeito dentro desse namespace e as operações de montagem no namespace pai têm efeito apenas fora do novo namespace.
Exceto, isto é, para montagens compartilhadas. Uma montagem pode ser compartilhada , em cujo caso as operações afetam todos os namespaces em que a montagem é compartilhada. Um caso de uso típico para montagens compartilhadas é disponibilizar unidades removíveis em namespaces filhos, como chroots. Existem mais tipos de relacionamentos (montagens privadas, montagens não acessíveis); para mais detalhes, veja a documentação do kernel .
Você pode verificar se uma montagem é compartilhada verificando /proc/PID/mountinfo
: se a linha contiver shared:NUMBER
, a montagem é compartilhada e o número é um valor exclusivo que identifica o conjunto de namespaces com os quais ele é compartilhado. Se a linha não contiver tal indicação, a montagem é privada.
No seu sistema, /proc
é compartilhado. Quando você monta uma nova instância de proc no namespace filho, já que você está montando sobre /proc
do pai, essa nova instância também é compartilhada, portanto, é visível tanto no namespace filho quanto no namespace pai. Quando você sai do namespace filho, a segunda instância de /proc
permanece montada, já que é compartilhada com o namespace pai ainda ativo.
Duas coisas complicam seu cenário: você também está criando um namespace PID e está usando /proc
como assunto da experiência e como meio de observação. Quando ps
reclama sobre /proc
não estar montado, ele está realmente exibindo uma mensagem de erro enganosa - o errado proc
está montado (a proc
para o namespace errado). Você pode observar isso com ls /proc
e cat /proc/1/mountinfo
. Eu recomendo fazer os experimentos com um sistema de arquivos scratch, seria mais fácil entender o que estava acontecendo.
parent# ./a.out child# echo $$ 2 child# ls /proc This is the parent's proc, with /proc/PID in the parent PID namespace child# ps 1 … init child# mount -t proc proc /proc Now /proc in the child mount namespace is for the child PID namespace child# ps 1 … a.out child# exit parent#
Até agora, não importava se /proc
era particular ou compartilhado, mas agora é. Se /proc
for privado, nesse ponto, observaremos o /proc
do pai, que nunca foi afetado e mostra o namespace PID. Mas se /proc
for compartilhado, o comando mount
que emitimos anteriormente afetou os dois namespaces:
parent# ls /proc acpi asound buddyinfo … parent# ps 1 Error, do this: mount -t proc proc /proc Actually, /proc is mounted, but it's the proc for the PID namespace that we created earlier and now has zero running processes. parent# grep -c ' /proc ' /proc/mounts 2 parent# umount /proc We've unmounted the child PID namespace's /proc that was shadowing the parent namespace's /proc, so the “normal” /proc is visible again. parent# ps 1 … init