Linux · 8 min read · Feb 03, 2026

Entrando em um Espelho Seguro Ao Fazer Login Com Unionfs E Chroot

Entrando em um Espelho Seguro Ao Fazer Login Com Unionfs E Chroot

1. Introdução

Ao ler uma ‘dica’ no site do LinuxFromScratch, descobri as capacidades especiais do unionfs, especialmente em combinação com chroot. Mais tarde, li um HowTo em um wiki da Gentoo, sobre como entrar em um diretório home chrooted ao usar um script especial como shell. Combinando esses dois, cheguei a usar um ambiente chrooted, que você entra ao fazer login como um usuário especial. Este ambiente é uma cópia exata (espelho) do sistema em que você está trabalhando. Como você está em uma cópia segura do sistema real, pode fazer o que quiser, nunca mudará o sistema, tudo permanece dentro do cache (o ramo de leitura e gravação).

Links:
TRIP, um Empacotador TRIvial para LFS (e outros sistemas linux) - Dica original no site do LFS
Home_directory_jail - Guia para configurar uma prisão chroot na Gentoo

2. Técnica básica

Faça o que quiser, instale, mude e remova arquivos do sistema, e nenhum dano será causado. Seu sistema real permanece intocado. Isso pode soar como mágica, mas na realidade é apenas possível combinando algumas técnicas de todas as disponíveis para Linux.
Usando o sistema de arquivos Unionfs, um chroot e alguns diretórios remontados bem escolhidos, você pode configurar este sistema virtual.

2.1 Unionfs

A parte mais importante é o uso do unionfs. O Unionfs lhe dá a possibilidade de criar um sistema de arquivos, que é a união de pelo menos dois outros. Veja www.unionfs.org para mais informações. Agora, ao deixar o novo sistema de arquivos ser a união do nosso sistema de arquivos original (a raiz) em modo somente leitura, e de um sistema de arquivos temporário (o cache) em modo de leitura e gravação, você terá um sistema de arquivos que parece exatamente como seu sistema de arquivos original, mas no qual você pode modificar, excluir e/ou adicionar arquivos sem fazer nada ao seu sistema original. Isso não é possível, porque a raiz está montada como somente leitura. Cada modificação é armazenada pelo unionfs no cache.
A única diferença entre o sistema original e o recém-criado é o caminho: no novo sistema, ele sempre começa com o caminho do ponto de montagem da união. É por isso que o próximo passo é necessário.

Uma nota especial: hoje [junho de 2007] parece que o unionfs será incluído no kernel. O Unionfs está passando por um intenso desenvolvimento neste momento. Veja o site para mais informações.

No site, você encontrará informações sobre como habilitar o unionfs. Para os kernels mais recentes (posteriores a 2.6.19), há um patch para a fonte do kernel, para kernels não tão recentes, há um módulo externo.

2.2 (Re)Montagem

Uma coisa extra que você terá que fazer é (re)montar vários diretórios cruciais como /dev, /proc e /sys. Isso ocorre porque o sistema de arquivos da união não preserva os pontos de montagem existentes.
Também é recomendado remontar alguns diretórios especiais como /tmp e o diretório em que você está construindo o software.

2.3 Chroot

Ao chrootar para este ponto de montagem, você entra em um ambiente que é absolutamente uma cópia do seu sistema. Você pode fazer o que quiser, até remover diretórios e arquivos cruciais. Teste! Veja até onde você pode ir antes que seu sistema fique preso.

2.4 Fazendo login neste ambiente

Como o conceito explicado em Home_directory_jail, é possível criar um shell de login especial para entrar no ambiente criado com unionfs e chroot.
A ideia explicada aqui é criar um usuário especial, com um shell especial. Este shell fará, antes de entrar em um shell interativo, primeiro os passos necessários, como montar o sistema de arquivos da união, remontar alguns diretórios importantes e fazer o chroot.

3. Preparação

3.1 A partição de cache

Para iniciar uma partição com espaço suficiente para funcionar como cache. Isso não precisa ser uma partição física, pode ser um disco virtual.

Crie este disco com:

dd if=/dev/zero of=/mnt/cache.img bs=1M count=500  
mkfs.ext2 /mnt/cache.img  
mkdir /mnt/cache  
mount /mnt/cache.img /mnt/cache -o loop
chmod 777 /mnt/cache
mkdir /mnt/union

Isso cria uma partição (ou disco) virtual de 500M.

(Nota: o dispositivo de loopback deve ser suportado no seu kernel. Kernels da maioria das distribuições fazem isso.)

3.2 Shell de login especial

Crie um script shell chroot-union que fará todos os passos necessários:

O script chroot-union em /bin:

#!/bin/bash
function mount_unionfs {
# montar sistemas de arquivos temporários
if [ -z "$(mount -t unionfs | grep -w /mnt/union )" ]; then
    sudo /bin/mount -t unionfs -o dirs=/mnt/cache:/=ro unionfs /mnt/union
    
fi
if [ -n "$(mount -t unionfs | grep -w /mnt/union )" ]; then
    # montagens básicas do sistema
    if [ -z "$(mount | grep -w /mnt/union/dev)" ]; then
    sudo /bin/mount --bind /dev /mnt/union/dev 2> /dev/null
    fi
    
    if [ -z "$(mount -t devpts | grep -w /mnt/union/dev/pts)" ]; then
    sudo /bin/mount -t devpts devpts /mnt/union/dev/pts 2> /dev/null
    fi
    if [ -z "$(mount -t tmpfs | grep -w /mnt/union/dev/shm)" ]; then
    sudo /bin/mount -t tmpfs shm /mnt/union/dev/shm 2> /dev/null
    fi
    
    if [ -z "$(mount -t sysfs | grep -w /mnt/union/sys)" ]; then
    sudo /bin/mount -t sysfs sysfs /mnt/union/sys 2> /dev/null
    fi
    
    if [ -z "$(mount -t proc | grep -w /mnt/union/proc)" ]; then
    sudo /bin/mount -t proc proc /mnt/union/proc 2> /dev/null
    fi
    if [ -z "$(mount | grep -w /mnt/union/tmp)" ]; then
    sudo /bin/mount --bind /tmp /mnt/union/tmp 2> /dev/null
    fi
    
    
else
    echo "Montagem de /mnt/union falhou."
    
    exit 2
fi
    
}
function umount_unionfs {
#
# desmontar /tmp
#
if [ -n "$(mount | grep -w /mnt/union/tmp)" ]; then
    sudo /bin/umount /mnt/union/tmp 2> /dev/null
fi
#
# desmontar /proc
#
if [ -n "$(mount -t proc | grep -w /mnt/union/proc)" ]; then
    sudo /bin/umount /mnt/union/proc 2> /dev/null
fi
#
# desmontar /sys
#
if [ -n "$(mount -t sysfs | grep -w /mnt/union/sys)" ]; then
    sudo /bin/umount /mnt/union/sys 2> /dev/null
fi
#
# desmontar /dev/shm
#
if [ -n "$(mount -t tmpfs | grep -w /mnt/union/dev/shm)" ]; then
    sudo /bin/umount /mnt/union/dev/shm 2> /dev/null
fi
#
# desmontar /dev/pts
#
if [ -n "$(mount -t devpts | grep -w /mnt/union/dev/pts)" ]; then
    sudo /bin/umount /mnt/union/dev/pts 2> /dev/null
fi
#
# desmontar /dev
#
if [ -n "$(mount | grep -w /mnt/union/dev)" ]; then    
sudo /bin/umount /mnt/union/dev 2> /dev/null
fi
if [ -n "$(mount | grep -w /mnt/union )" ]; then  
sudo /bin/umount /mnt/union 2> /dev/null
fi
}
mount_unionfs
# entrar no chroot
sudo /usr/sbin/chroot /mnt/union /bin/su --shell /bin/bash --login $USER
# desmontar sistemas de arquivos temporários
umount_unionfs
EOF

Adicione o novo shell de login ao arquivo /etc/shells. Você terá que fazer isso quando o PAM verificar o shell.

3.3 Criar usuário e grupo.

Crie um novo grupo e usuário com este script como shell:

groupadd -g 27 uniongroup  
useradd -c "Usuário de teste para chrooted union." -d /home/unionuser \  
-m -s /bin/chroot-union -g uniongroup -u 27 unionuser  
passwd unionuser

3.4 Dar ao usuário direitos suficientes

Dê ao novo usuário mais direitos com sudo. Adicione a seguinte linha ao arquivo de configuração do sudo, /etc/sudoers:


unionuser ALL=(ALL) ALL

Nota: existem outras maneiras de dar a esse usuário as permissões. Estou analisando-as neste momento.

Nota: dar essas permissões totais é demais para um usuário normal. Mas para um usuário que instalará software e modificará seu sistema, é necessário.

O que é possível

Ambiente seguro e protegido para usuários normais

Esta construção é muito adequada para usuários convidados, que você não pode confiar. A primeira coisa que tentei foi iniciar uma sessão gráfica. Não tive nenhum problema.

Instalar software como este usuário

Outro uso possível é a instalação de software como este usuário. Isso pode ser feito da seguinte forma:

  • como este usuário, instale seu software. Devido à construção especial, todas as alterações vão para o cache.
  • após fazer logout, compare o conteúdo do cache com o sistema real.
  • o usuário controlador (root) tem a escolha de fazer a instalação real simplesmente movendo o conteúdo do cache para a raiz

Por exemplo, a compilação e instalação de um pequeno pacote, audiofile-0.2.6. Suponha que a fonte esteja em /tmp. Primeiro login:

[root@hostname ]# login  
hostname login: unionuser  
Password:  
Last login: Wed Jun 20 19:58:32 CEST 2007 on pts/0  
[unionuser@hostname ]$

Agora compile e instale o pacote:

[unionuser@hostname ]$ cd /tmp/audiofile-0.2.6
[unionuser@hostname ]$ ./configure –prefix=/usr
[unionuser@hostname ]$ make
[unionuser@hostname ]$ sudo make install

Agora saia da sessão e verifique o conteúdo do cache:

[unionuser@hostname ]$exit
[root@hostname ]# cd /mnt/cache
[root@hostname ]# ls -Al
drwxr-xr-x 3 root root 1024 2007-06-05 17:32 home
drwxr-xr-x 6 root root 1024 2007-06-05 17:37 usr
drwxr-xr-x 3 root root 1024 2007-06-05 17:32 var
[root@hostname ]#

O diretório home aparece aqui porque o shell Bash altera o arquivo .bash_history; o diretório var aparece devido a alterações no arquivo /var/run/utmp e no diretório /var/run/sudo. Isso prova que funciona como deveria.

Agora, ao olhar para as alterações no diretório /usr onde instalei o software, temos:

[root@hostname ]# find usr -type f
usr/lib/pkgconfig/audiofile.pc
usr/lib/libaudiofile.la
usr/lib/libaudiofile.a
usr/lib/libaudiofile.so.0.0.2
usr/include/audiofile.h
usr/include/aupvlist.h
usr/include/af_vfs.h
usr/bin/audiofile-config
usr/bin/sfconvert
usr/bin/sfinfo
usr/share/aclocal/audiofile.m4
[root@hostname ]# find usr -type d
usr
usr/lib
usr/lib/pkgconfig
usr/include
usr/bin
usr/share
usr/share/aclocal

Como você pode ver, tudo está no diretório /mnt/cache/usr.

Você pode fazer um backup disso:

[root@hostname ]# find usr | sort -u > /tmp/filelist-audiofile-0.2.6  
  
[root@hostname ]# tar --create --files-from=/tmp/filelist-audiofile-0.2.6 \  
                  --file=/tmp/install-audiofile-0.2.6.tar --directory=/mnt/cache \  
                  --no-recursion --absolute-names --preserve-permissions

É também muito possível fazer um backup de todos os arquivos que serão sobrescritos:

[root@hostname ]# for installfile in $(cat /tmp/filelist-audiofile-0.2.6); do \  
                    if [ -e "/$installfile ]; then \  
                      echo "/$installfile" >> /tmp/backup-audiofile-0.2.6 \  
                    fi \  
                  done  
[root@hostname ]# tar --create --files-from=/tmp/backup-audiofile-0.2.6 \  
                  --file=/tmp/backup-audiofile-0.2.6.tar --directory=/mnt/cache \  
                  --no-recursion --absolute-names --preserve-permissions

Agora faça a instalação real copiando todos os arquivos para a raiz:

[root@hostname ]# for installfile in $(cat /tmp/filelist-audiofile-0.2.6); do \  
                    cp --verbose --force --recursive --parents --no-dereference \  
                      --preserve --target-directory=/ $installfile \  
                  done

Nota: os comandos acima são para ilustrar a ideia. Eu criei scripts que fazem o backup, verificação e instalação, e funciona muito bem.

Share: X/Twitter LinkedIn

Receba novas postagens na sua caixa de entrada

Sem spam. Cancele a assinatura a qualquer momento.