Como sei se estou executando um chroot?


47

Eu tenho uma instalação unix que deveria ser usada tanto como chroot quanto como sistema independente. Se estiver executando como chroot, não quero executar nenhum serviço (cron, inetd etc.), porque eles entrariam em conflito com o sistema host ou seriam redundantes.

Como escrevo um script de shell que se comporta de maneira diferente, dependendo de estar sendo executado em um chroot? Minha necessidade imediata é de um sistema Linux moderno, /procmontado no chroot, e o script esteja sendo executado como root, mas respostas mais portáteis também serão bem-vindas. (Consulte Como saber se estou executando um chroot se / proc não estiver montado? Para o caso do Linux sem /proc.)

De maneira mais geral, sugestões que funcionem para outros métodos de contenção seriam interessantes. A questão prática é: esse sistema deveria estar executando algum serviço? (A resposta é não em um chroot e sim em máquinas virtuais completas; não conheço casos intermediários, como cadeias ou contêineres.)

Respostas:


46

O que eu fiz aqui é testar se a raiz do initprocesso (PID 1) é igual à raiz do processo atual. Embora /proc/1/rootseja sempre um link para /(a menos que initele seja chrootado, mas esse não é um caso que me importe), segui-lo leva ao diretório raiz "mestre". Esta técnica é usada em alguns scripts de manutenção no Debian, por exemplo, para pular o início do udev após a instalação em um chroot.

if [ "$(stat -c %d:%i /)" != "$(stat -c %d:%i /proc/1/root/.)" ]; then
  echo "We are chrooted!"
else
  echo "Business as usual"
fi

(A propósito, este é mais um exemplo de por que chrooté inútil para a segurança se o processo chroot tiver acesso root. Processos não raiz não podem ler /proc/1/root, mas podem ser seguidos /proc/1234/rootse houver um processo em execução com o PID 1234 sendo executado da mesma forma. do utilizador.)

Se você não possui permissões de root, pode ver /proc/1/mountinfoe /proc/$$/mountinfo(brevemente documentado na documentação filesystems/proc.txtdo kernel do Linux ). Este arquivo é legível por todo o mundo e contém muitas informações sobre cada ponto de montagem na visualização do processo do sistema de arquivos. Os caminhos nesse arquivo são restritos pelo chroot que afeta o processo do leitor, se houver. Se a leitura do processo /proc/1/mountinfofor chroot em um sistema de arquivos diferente da raiz global (supondo que a raiz do pid 1 seja a raiz global), nenhuma entrada para será /exibida /proc/1/mountinfo. Se a leitura do processo /proc/1/mountinfofor chroot para um diretório no sistema de arquivos raiz global, uma entrada para /aparecerá /proc/1/mountinfo, mas com um ID de montagem diferente. Aliás, o campo raiz ($4) indica onde o chroot está em seu sistema de arquivos mestre.

[ "$(awk '$5=="/" {print $1}' </proc/1/mountinfo)" != "$(awk '$5=="/" {print $1}' </proc/$$/mountinfo)" ]

Esta é uma solução Linux pura. Pode ser generalizável para outras variantes do Unix com uma similaridade suficiente /proc(o Solaris tem uma similar /proc/1/root, eu acho, mas não mountinfo).


1
Isso não funcionará no OpenBSD porque possui PIDs aleatórios ; o processo raiz nunca é basicamente o PID 1. Agora você sabe o porquê!
Adam Katz

@AdamKatz "... com algumas exceções óbvias, por exemplo, init (8)." Então qual é?
Muru

@ muru: aw, shucks. Você me derrubou. Não sei por init(8)que absolutamente precisaria ter o slot número 1, a menos que exista algum tipo de natureza codificada que o exija (no qual eu ainda não teria certeza do porquê ). Obviamente, os BSDs têm cadeias muito mais avançadas do que apenas chroot, então nem tenho certeza de quão problemático isso é.
Adam Katz

4
@AdamKatz É o oposto: o pid 1 tem um papel especial (deve colher zumbis e é imune a SIGKILL). O programa init é uma implementação dessa função. A razão pela qual minha resposta não funciona no OpenBSD não tem nada a ver com isso: é porque o OpenBSD não tem nada parecido com o Solaris / Linux /proc. Minha resposta não foi feita para resolver nada além do Linux.
Gilles 'SO- stop be evil'

@Gilles, imaginei que o OpenBSD teria isso derrotado de uma maneira ou de outra. Ainda assim, estou surpreso que todos esses itens de função especial não possam ser aplicados a um PID arbitrário (sem consequências), que é o que eu quis dizer no meu "porquê" em itálico anterior.
Adam Katz

22

Conforme mencionado na maneira Portátil para encontrar o número do inode e Detectando uma cadeia chroot de dentro , você pode verificar se o número do inode /é 2:

$ ls -di /
2 /

Um número de inode diferente de 2 indica que a raiz aparente não é a raiz real de um sistema de arquivos. Isso não detectará chroots que estão enraizados em um ponto de montagem ou em sistemas operacionais com números aleatórios de inodes de raiz .


Em quais sistemas de arquivos essa heurística funciona?
Gilles 'SO- stop be evil'

Testado em ext3 e hfs.
l0b0

Então, eu estava brincando e acho que encontrei um método mais confiável que não requer permissões de root (somente Linux). Ainda estou aberto a contra-exemplos ou métodos mais portáteis.
Gilles 'SO- stop be evil'

6
Isso é verdade para o ext [234], mas não para todos os sistemas de arquivos. Também testa apenas se sua raiz é a raiz do sistema de arquivos, que pode não ser montada como a raiz real. Em outras palavras, se você montar outra partição no / jail e chroot /jail, ela parecerá a raiz real deste teste.
Psusi

1
@AdamKatz Aparentemente não. Testado no openbsd 6.0-stable, o número do inode ainda é 2 para o caminho raiz real, enquanto é um número aleatório para o chroot.
Dmitri DB

5

Embora claramente não seja tão portátil quanto muitas outras opções listadas aqui, se você estiver em um sistema baseado em Debian, tente ischroot.

Veja: https://manpages.debian.org/jessie/debianutils/ischroot.1.en.html

Para obter o status diretamente no console, usando ischroot:

ischroot;echo $?

Códigos de saída:

0 if currently running in a chroot
1 if currently not running in a chroot
2 if the detection is not possible (On GNU/Linux this happens if the script is not run as root).
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.