chroot: Alterando o Diretório Raiz para Isolar um Ambiente

chroot: Alterando o Diretório Raiz para Isolar um Ambiente

O Que Você Vai Aprender

  • Como o chroot troca o diretório raiz que um processo enxerga
  • Como diagnosticar "o comando não executa dentro do chroot" como um problema de bibliotecas compartilhadas
  • Um fluxo de trabalho confiável de recuperação de sistema a partir de USB live ou modo de resgate
  • Por que o chroot não é um limite de segurança e o que usar no lugar

Resumo Rápido

  • O chroot apenas altera a visão do sistema de arquivos. Ele não isola processos nem rede.
  • O binário do comando e suas bibliotecas compartilhadas devem existir dentro da nova raiz.
  • Para recuperação, faça bind-mount de /dev, /proc e /sys antes do chroot.
  • Para isolamento real, use containers (namespaces), não chroot.

Pré-requisitos

  • SO: Família Ubuntu / Debian (comandos são idênticos em sistemas da família RHEL)
  • Executar chroot requer privilégios de root (CAP_SYS_CHROOT)
  • O comando chroot vem com o coreutils (nenhuma instalação extra necessária)

O Que é chroot?

Conclusão: O chroot altera o diretório raiz aparente (/) de um processo e seus filhos para um diretório que você especifica, de modo que esse processo não consiga mais acessar arquivos fora da nova raiz.

Normalmente, todo processo resolve caminhos a partir da raiz do sistema /. Quando você executa chroot /mnt/newroot, tudo abaixo desse ponto se torna o novo / para o processo afetado.

$ sudo chroot /mnt/newroot

A partir desse momento, o /etc/passwd do shell chrooted na verdade aponta para /mnt/newroot/etc/passwd. Qualquer coisa fora da nova raiz (o /home real do host, por exemplo) não pode mais ser referenciada como caminho. É por isso que o chroot é descrito como "isolar um ambiente."

Um ambiente chrooted é convencionalmente chamado de chroot jail -- o processo está "preso" e não consegue ver a árvore de arquivos fora da sua nova raiz.

Por Que Usar chroot?

Conclusão: Os três usos principais são recuperação de sistema, ambientes limpos de build/teste e confinamento de serviço. Use-o quando quiser executar um comando contra um sistema de arquivos independente do que está em execução.

Casos de uso típicos:

Caso de uso Exemplo
Recuperação de sistema Iniciar com USB live, chroot no SO que não inicia, reinstalar grub ou redefinir uma senha
Ambiente limpo Compilar um pacote dentro de uma raiz mínima pristina criada com debootstrap
Confinamento Restringir usuários SFTP públicos ao seu diretório home (sshd ChrootDirectory)
Validação Executar o userland de outra distro sobre o kernel existente

O chroot não troca o kernel. Mesmo que a nova raiz contenha bibliotecas e binários diferentes, o kernel em execução continua sendo o do host.

Como Executar chroot?

Conclusão: A sintaxe é chroot NOVARAIZ [COMANDO]. Omita o comando e ele inicia o shell do usuário ($SHELL ou /bin/sh) interativamente. Privilégios de root são necessários.

Sintaxe básica:

$ sudo chroot NOVARAIZ [COMANDO [ARG...]]

Sem um comando:

# Iniciar um shell interativo dentro da nova raiz
$ sudo chroot /mnt/newroot

Com um comando explícito:

# Executar /bin/ls dentro da nova raiz e sair
$ sudo chroot /mnt/newroot /bin/ls -l /

O caminho que você fornece para COMANDO é absoluto relativo à nova raiz. chroot /mnt/newroot /bin/bash executa /mnt/newroot/bin/bash, não o caminho do host.

O Que um Ambiente chroot Precisa?

Conclusão: Além do binário do comando em si, as bibliotecas compartilhadas (arquivos .so) das quais ele depende devem existir dentro da nova raiz. Caso contrário, ele falha com "No such file or directory."

Essa é a armadilha clássica. Executar chroot /mnt/newroot /bin/bash falha se /mnt/newroot/bin/bash estiver ausente -- e mesmo quando o binário está presente, as bibliotecas compartilhadas que o bash referência também devem estar dentro da nova raiz.

Encontre as dependências com ldd:

$ ldd /bin/bash
        linux-vdso.so.1 (0x00007fff...)
        libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f...)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f...)
        /lib64/ld-linux-x86-64.so.2 (0x00007f...)

Copie cada .so para o mesmo caminho dentro da nova raiz e o bash funcionará. Um jail mínimo construído manualmente:

$ NEWROOT=/mnt/jail
$ sudo mkdir -p $NEWROOT/{bin,lib,lib64}
$ sudo cp /bin/bash $NEWROOT/bin/
# Copie os arquivos .so reportados pelo ldd nos diretorios correspondentes
$ sudo cp /lib/x86_64-linux-gnu/{libtinfo.so.6,libc.so.6} $NEWROOT/lib/
$ sudo cp /lib64/ld-linux-x86-64.so.2 $NEWROOT/lib64/
$ sudo chroot $NEWROOT /bin/bash

Ambientes chroot do mundo real são construídos com debootstrap (Debian/Ubuntu) ou dnf --installroot (família RHEL), que montam um userland completo com dependências em um único passo. Trate a cópia manual acima como uma forma de entender o mecanismo.

Recuperando um Sistema com chroot

Conclusão: Para reparar um SO que não inicializa, monte o disco, faça bind-mount de /dev, /proc e /sys nele e depois faça chroot. Isso permite operar o SO instalado quase como se tivesse inicializado normalmente.

Passos para entrar no SO instalado a partir de um USB live ou modo de resgate, assumindo que /dev/sda1 é a partição raiz:

# 1. Monte a particao raiz do alvo
$ sudo mount /dev/sda1 /mnt

# 2. Disponibilize os sistemas de arquivos virtuais via bind mounts
$ sudo mount --bind /dev  /mnt/dev
$ sudo mount --bind /proc /mnt/proc
$ sudo mount --bind /sys  /mnt/sys

# 3. Faca chroot no SO instalado
$ sudo chroot /mnt

# 4. Agora opere normalmente (ex: reinstalar o GRUB)
# grub-install /dev/sda && update-grub

Sem /dev, /proc e /sys, comandos que leem informações do kernel ou dispositivos -- como grub-install ou operações de pacotes -- falharão. Esses bind mounts são efetivamente obrigatórios para um chroot de recuperação.

Quando terminar, saia do chroot antes de desmontar. Inverter a ordem resulta em target is busy.

# Saia do chroot primeiro
# exit

$ sudo umount /mnt/sys /mnt/proc /mnt/dev
$ sudo umount /mnt

Alguns casos também precisam de /dev/pts (pseudo-terminais) ou /run. O arch-chroot (fornecido pelo Arch Linux mas utilizável em outros sistemas) é um wrapper conveniente que configura esses bind mounts para você.

O chroot é um Limite de Segurança?

Conclusão: Não. O chroot apenas altera a visão do sistema de arquivos; um processo com privilégios de root pode escapar dele usando técnicas bem conhecidas. Use containers baseados em namespaces para isolamento real.

Tratar o chroot como sandbox é perigoso. Um processo executando como root dentro de um chroot pode escapar (um "chroot escape") com truques clássicos como um chroot duplo. Isso é uma limitação de design, não um bug.

O que o chroot não isola:

  • A tabela de processos (ps enxerga processos externos, e você pode usar kill neles)
  • Rede (a mesma pilha de rede é compartilhada)
  • Usuários e privilégios (root dentro do chroot é o root do host)
  • O kernel (compartilhado)

Para confinar de forma segura usuários sem privilégios, opções práticas incluem o ChrootDirectory do sshd (confinamento somente SFTP) e configurações de serviço do systemd como RootDirectory= combinado com PrivateDevices=.

Erros Comuns e Soluções

Conclusão: A maioria das falhas se resume a bibliotecas compartilhadas ausentes, bind mounts ausentes ou privilégios insuficientes. Leia a mensagem de erro para distingui-las.

chroot: failed to run command '/bin/bash': No such file or directory

Se o binário do bash existe mas você ainda vê este erro, as bibliotecas compartilhadas (incluindo o loader) estão ausentes dentro da nova raiz em quase todos os casos. Combine a saída do ldd /bin/bash na nova raiz (veja a seção de dependências).

$ ldd /bin/bash   # Execute no host para listar os arquivos .so necessarios

chroot: cannot change root directory to '/mnt': Operation not permitted

Você não tem privilégios de root -- adicione sudo. O mesmo erro aparece quando CAP_SYS_CHROOT foi removido, como dentro de um container.

Muitos "command not found" após chroot

Ou o PATH não corresponde ao layout da nova raiz, ou os comandos necessários não estão instalados. Uma raiz mínima pode não conter nem mesmo ls. Monte um userland completo com debootstrap ou similar.

umount reporta target is busy

Você está tentando desmontar antes de sair do shell chroot. Faça exit do chroot primeiro, depois desmonte na ordem /sys, /proc, /dev, /mnt.

Copie e cole: template seguro de chroot para recuperação

# Entrar
sudo mount /dev/sda1 /mnt
sudo mount --bind /dev  /mnt/dev
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys  /mnt/sys
sudo chroot /mnt

# Apos o trabalho, saia do chroot e depois:
sudo umount /mnt/sys /mnt/proc /mnt/dev
sudo umount /mnt

Próximas Leituras