Depois de ler sobre os namespaces do Linux, tive a impressão de que eles são, entre muitos outros recursos, uma alternativa ao chroot. Por exemplo, neste artigo :
Outros usos [de espaços para nome] incluem [...] isolamento ao estilo chroot () de um processo em uma parte da hierarquia de diretório único.
No entanto, quando clono o espaço para nome da montagem, por exemplo, com o seguinte comando, ainda vejo toda a árvore raiz original.
unshare --mount -- /bin/bash
Entendo que agora posso realizar montagens adicionais no novo espaço para nome que não são compartilhadas com o espaço para nome original e, portanto, isso fornece isolamento, mas ainda é a mesma raiz, por exemplo, /etc
ainda é a mesma para os dois espaços para nome. Ainda preciso chroot
alterar a raiz ou existe uma alternativa?
Eu esperava que essa pergunta pudesse fornecer uma resposta, mas a resposta só usa chroot
novamente.
EDIT # 1
Agora, havia um comentário excluído mencionado pivot_root
. Como isso realmente faz parte linux/fs/namespace.c
, na verdade faz parte da implementação dos namespaces. Isso sugere que alterar o diretório raiz apenas com unshare
e mount
não é possível, mas os namespaces fornecem uma versão própria - mais inteligente - do chroot
. Ainda não entendi a idéia principal dessa abordagem que a torna fundamentalmente diferente chroot
, mesmo depois de ler o código-fonte (no sentido de, por exemplo, segurança ou melhor isolamento).
EDIT # 2
Esta não é uma duplicata desta pergunta . Depois de executar todos os comandos da resposta, tenho /tmp/tmp.vyM9IwnKuY (ou similar), mas o diretório raiz ainda é o mesmo!
pivot_root
echroot
: dei uma olhada nas fontes do Docker e descobri que, se ele falha na execuçãopivot_root
, ele volta achroot
, ou seja, esses mecanismos são considerados pelo menos semelhantes em funcionalidade para fins de contêiner.Respostas:
Inserir um espaço para nome de montagem antes de configurar um
chroot
, permite evitar o espaço para nome do host com montagens adicionais, por exemplo, para/proc
. Você pode usarchroot
dentro de um namespace mount como um hack simples e agradável.Eu acho que há vantagens em entender
pivot_root
, mas tem uma curva de aprendizado. A documentação não explica tudo muito bem ... embora haja um exemplo de uso emman 8 pivot_root
(para o comando shell).man 2 pivot_root
(para a chamada do sistema) pode ser mais claro se fizer o mesmo e incluir um exemplo de programa C.Como usar pivot_root
Imediatamente após inserir o espaço para nome da montagem, você também precisa
mount --make-rslave /
ou equivalente. Caso contrário, todas as suas alterações de montagem serão propagadas para as montagens no espaço para nome original, incluindo opivot_root
. Você não quer isso :).Se você usou o
unshare --mount
comando, observe que ele está documentado para ser aplicadomount --make-rprivate
por padrão. AFAICS, esse é um padrão ruim e você não deseja isso no código de produção. Por exemplo, nesse ponto, ele deixariaeject
de funcionar em um DVD ou USB montado no espaço para nome do host. O DVD ou USB permaneceria montado dentro da árvore de montagem privada e o kernel não permitiria ejetar o DVD.Depois de fazer isso, você pode montar, por exemplo, o
/proc
diretório que você usará. Da mesma maneira que você fariachroot
.Diferentemente de quando você usa
chroot
,pivot_root
requer que seu novo sistema de arquivos raiz seja um ponto de montagem. Se não for um já, você pode satisfazer esta simplesmente aplicando montar um ligamento:mount --rbind new_root new_root
.Use
pivot_root
- e, em seguida,umount
o antigo sistema de arquivos raiz, com a opção-l
/MNT_DETACH
. ( Você não precisaumount -R
, o que pode levar mais tempo. ).Tecnicamente, o uso
pivot_root
geralmente precisa envolver o usochroot
também; não é "um ou outro".Conforme
man 2 pivot_root
definido, é definido apenas como a troca da raiz do espaço para nome da montagem. Não está definido para alterar para qual diretório físico a raiz do processo está apontando. Ou o diretório de trabalho atual (/proc/self/cwd
). Acontece que isso acontece , mas este é um truque para lidar com os threads do kernel. A página de manual diz que isso pode mudar no futuro.Geralmente você deseja esta sequência:
A publicação do
chroot
nesta sequência é mais um detalhe sutil . Embora o objetivopivot_root
seja reorganizar o espaço para nome da montagem, o código do kernel parece encontrar o sistema de arquivos raiz movendo-se olhando a raiz por processo, que é o quechroot
define.Por que usar pivot_root
Em princípio, faz sentido usar
pivot_root
para segurança e isolamento. Eu gosto de pensar sobre a teoria da segurança baseada em capacidade . Você passa uma lista dos recursos específicos necessários e o processo não pode acessar outros recursos. Neste caso, estamos falando sobre os sistemas de arquivos passados para um espaço para nome de montagem. Essa ideia se aplica geralmente ao recurso "namespaces" do Linux, embora provavelmente não esteja expressando muito bem.chroot
define apenas a raiz do processo, mas o processo ainda se refere ao namespace de montagem completa. Se um processo reter o privilégio de executarchroot
, ele poderá percorrer o espaço de nome do sistema de arquivos. Conforme detalhado emman 2 chroot
"o superusuário pode escapar de uma 'prisão chroot' até ...".Outra maneira instigante de desfazer
chroot
énsenter --mount=/proc/self/ns/mnt
. Este é talvez um argumento mais forte para o princípio.nsenter
/setns()
necessariamente recarrega a raiz do processo, a partir da raiz do namespace mount ... embora o fato de que isso funcione quando os dois se refiram a diretórios físicos diferentes, possa ser considerado um bug do kernel. (Nota técnica: pode haver vários sistemas de arquivos montados um sobre o outro na raiz;setns()
usa o topo, mais recentemente montado).Isso ilustra uma vantagem de combinar um espaço para nome de montagem com um "espaço para nome PID". Estar dentro de um espaço de nome PID impediria a inserção do espaço para nome de montagem de um processo não confinado. Também impede que você entre na raiz de um processo não confinado (
/proc/$PID/root
). E, é claro, um espaço para nome PID também impede que você interrompa qualquer processo que esteja fora dele :-).fonte
mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL)
umount -l ./oldroot
pivot_root(".", ".")
truque, que é realmente a maneira mais fácil de usarpivot_root
na maioria das circunstâncias (não échroot
necessário).