Unionfs e Chroot · 8 min read · Feb 03, 2026

Entrare in uno Specchio Sicuro Durante il Login con Unionfs e Chroot

Entrare in uno Specchio Sicuro Durante il Login con Unionfs e Chroot

1. Introduzione

Quando leggevo un ‘suggerimento’ sul sito di LinuxFromScratch, ho scoperto le capacità speciali di unionfs, specialmente in combinazione con chroot. Più tardi ho letto un HowTo su un wiki di Gentoo, riguardo all’ingresso in una home directory chrooted quando si utilizza uno script speciale come shell. Combinando queste due cose, arrivo a utilizzare un ambiente chrooted, che si entra quando si effettua il login come un utente speciale. Questo ambiente è una copia esatta (specchio) del sistema su cui stai lavorando. Poiché sei in una copia sicura del sistema reale, puoi fare ciò che vuoi, non cambierà mai il sistema, tutto rimane all’interno della cache (il ramo readwrite).

Link:
TRIP, un TRIvial Packager per LFS (e altri sistemi linux) - Suggerimento originale sul sito di LFS
Home_directory_jail - Guida per impostare una chroot jail su Gentoo

2. Tecnica di base

Fai ciò che vuoi, installa, modifica e rimuovi file dal sistema, e nessun danno. Il tuo sistema reale rimane intatto. Questo può sembrare magia, ma in realtà è possibile solo combinando alcune tecniche di tutte quelle disponibili per Linux.
Utilizzando il filesystem Unionfs, un chroot e alcune directory rimontate scelte con cura, puoi impostare questo sistema virtuale.

2.1 Unionfs

La parte più importante è l’uso di unionfs. Unionfs ti dà la possibilità di creare un filesystem, che è l’unione di almeno altri due. Vedi www.unionfs.org per ulteriori informazioni. Ora, facendo sì che il nuovo filesystem sia l’unione del nostro filesystem originale (la radice) in sola modalità lettura, e di un filesystem temporaneo (la cache) in modalità lettura-scrittura, avrai un filesystem che appare esattamente come il tuo filesystem originale, ma in cui puoi modificare, eliminare e/o aggiungere file senza fare nulla al tuo sistema originale. Questo non è possibile, perché la radice è montata in sola lettura. Ogni modifica è memorizzata da unionfs nella cache.
L’unica differenza tra il sistema originale e quello appena creato è il percorso: nel nuovo sistema inizia sempre con il percorso del punto di mount dell’unione. Questo è il motivo per cui il passo successivo è necessario.

Una nota speciale: oggi [giugno 2007] sembra che unionfs sarà incluso nel kernel. Unionfs è attualmente in fase di sviluppo intenso. Controlla il sito web per ulteriori informazioni.

Sul sito troverai informazioni su come abilitare unionfs. Per i kernel più recenti (dopo il 2.6.19) c’è una patch per il kernel sorgente, per i kernel non così recenti c’è un modulo esterno.

2.2 (Re)Montaggio

Una cosa extra che dovrai fare è (re)montare diverse directory cruciali come /dev, /proc e /sys. Questo perché il filesystem union non preserva i punti di mount esistenti.
È anche consigliato rimontare alcune directory speciali come /tmp e la directory in cui stai costruendo il software.

2.3 Chroot

Chrootando a questo punto di mount, entri in un ambiente che è assolutamente una copia del tuo sistema. Puoi fare ciò che vuoi, anche rimuovere directory e file cruciali. Provalo! Guarda fino a che punto puoi arrivare prima che il tuo sistema si blocchi.

2.4 Effettuare il login in questo ambiente

Come il concetto spiegato in Home_directory_jail, è possibile creare una shell di login speciale per entrare nell’ambiente creato con unionfs e chroot.
L’idea spiegata qui è di creare un utente speciale, con una shell speciale. Questa shell, prima di entrare in una shell interattiva, eseguirà prima i passaggi necessari come montare il filesystem union, rimontare alcune directory importanti e fare il chroot.

3. Preparazione

3.1 La partizione cache

Per iniziare, una partizione con spazio sufficiente per funzionare come cache. Questa non deve essere una partizione fisica, può essere un’unità virtuale.

Crea questa unità con:

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

Questo crea una partizione virtuale (o unità) di 500M.

(Nota: il dispositivo loopback deve essere supportato nel tuo kernel. I kernel della maggior parte delle distribuzioni lo fanno.)

3.2 Shell di login speciale

Crea uno script shell chroot-union che eseguirà tutti i passaggi necessari:

Lo script chroot-union in /bin:

#!/bin/bash
function mount_unionfs {
# monta filesystem temporanei
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
    # montaggi di sistema di base
    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 "Il montaggio di /mnt/union è fallito."
    
    exit 2
fi
    
}
function umount_unionfs {
#
# smonta /tmp
#
if [ -n "$(mount | grep -w /mnt/union/tmp)" ]; then
    sudo /bin/umount /mnt/union/tmp 2> /dev/null
fi
#
# smonta /proc
#
if [ -n "$(mount -t proc | grep -w /mnt/union/proc)" ]; then
    sudo /bin/umount /mnt/union/proc 2> /dev/null
fi
#
# smonta /sys
#
if [ -n "$(mount -t sysfs | grep -w /mnt/union/sys)" ]; then
    sudo /bin/umount /mnt/union/sys 2> /dev/null
fi
#
# smonta /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
#
# smonta /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
#
# smonta /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
# entra nel chroot
sudo /usr/sbin/chroot /mnt/union /bin/su --shell /bin/bash --login $USER
# smonta filesystem temporanei
umount_unionfs
EOF

Aggiungi la nuova shell di login al file /etc/shells. Dovrai farlo quando PAM controllerà la shell.

3.3 Creare utente e gruppo.

Crea un nuovo gruppo e utente con questo script come shell:

groupadd -g 27 uniongroup  
useradd -c "Utente di test per chrooted union." -d /home/unionuser \  
-m -s /bin/chroot-union -g uniongroup -u 27 unionuser  
passwd unionuser

3.4 Dare all’utente abbastanza diritti

Dai al nuovo utente più diritti con sudo. Aggiungi la seguente riga al file di configurazione di sudo, /etc/sudoers:


unionuser ALL=(ALL) ALL

Nota: ci sono altri modi per dare a questo utente i permessi. Li sto esaminando in questo momento.

Nota: dare questi permessi completi è troppo per un utente normale. Ma per un utente che installerà software e modificherà il tuo sistema è necessario.

Cosa è possibile

Ambiente sicuro e protetto per utenti normali

Questa costruzione è molto adatta per utenti ospiti, di cui non ti puoi fidare. La prima cosa che ho provato è stata avviare una sessione grafica. Non ho avuto alcun problema.

Installare software come questo utente

Un altro possibile utilizzo è l’installazione di software come questo utente. Questo può essere fatto come segue:

  • come questo utente installa il tuo software. A causa della costruzione speciale, tutte le modifiche vanno nella cache.
  • dopo aver effettuato il logout, confronta il contenuto della cache con il sistema reale.
  • l’utente controllante (root) ha la possibilità di eseguire l’installazione reale semplicemente spostando il contenuto dalla cache alla radice.

Ad esempio, la compilazione e l’installazione di un piccolo pacchetto, audiofile-0.2.6. Supponiamo che la sorgente sia in /tmp. Prima login:

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

Ora compila e installa il pacchetto:

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

Ora esci dalla sessione e controlla il contenuto della 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 ]#

La directory home appare qui perché la shell Bash modifica il file .bash_history; la directory var appare a causa delle modifiche nel file /var/run/utmp e nella directory /var/run/sudo. Questo dimostra che funziona come dovrebbe.

Ora, guardando le modifiche nella directory /usr dove ho installato il software dà:

[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

Come puoi vedere, tutto è nella directory /mnt/cache/usr.

Puoi fare un backup di questo:

[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

È anche molto possibile fare un backup di tutti i file che verranno sovrascritti:

[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

Ora fai l’installazione reale copiando tutti i file nella radice:

[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: i comandi sopra sono per illustrare l’idea. Ho creato script che eseguono il backup, il controllo e l’installazione, e funziona molto bene.

Share: X/Twitter LinkedIn

Ricevi i nuovi post nella tua casella di posta.

Nessuno spam. Disiscriviti in qualsiasi momento.