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 usar chroot
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 em man 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 o pivot_root
. Você não quer isso :).
Se você usou o unshare --mount
comando, observe que ele está documentado para ser aplicado mount --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 deixaria eject
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ê faria chroot
.
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 precisa umount -R
, o que pode levar mais tempo. ).
Tecnicamente, o uso pivot_root
geralmente precisa envolver o uso chroot
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:
chdir(new_root); // cd new_root
pivot_root(".", put_old); // pivot_root . put_old
chroot("."); // chroot .
A publicação do chroot
nesta sequência é mais um detalhe sutil . Embora o objetivo pivot_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 que chroot
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 executar chroot
, ele poderá percorrer o espaço de nome do sistema de arquivos. Conforme detalhado em man 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 :-).
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.