Environnement chroot

De ArchwikiFR


Cette page regroupe quelques exemple de création d'environnement chroot. Vous pouvez avoir un aperçu des outils pour les utiliser sur la page utilisation chroot.

Chroot minimal

Préambule

Avant de nous lancer dans la construction d'un environnement chroot, une explication rapide sur le fonctionnement d'un exécutable binaire sous un système GNU/Linux: En dehors des fichiers de configuration, un exécutable binaire est un exécutable lié à une ou plusieurs bibliothèques partagées, pour pouvoir exécuter /bin/bash par exemple, il nous faut:

ldd /bin/bash
	linux-gate.so.1 =>  (0xb7fad000)
	libreadline.so.6 => /lib/libreadline.so.6 (0xb7f62000)
	libhistory.so.6 => /lib/libhistory.so.6 (0xb7f5a000)
	libncursesw.so.5 => /lib/libncursesw.so.5 (0xb7f0d000)
	libdl.so.2 => /lib/libdl.so.2 (0xb7f09000)
	libc.so.6 => /lib/libc.so.6 (0xb7dc3000)
	/lib/ld-linux.so.2 (0xb7fae000)

Note : Dans cette section, le répertoire de base est /home et l'environnement chroot est /home/chroot_env

Construction

Pour créer un environnement, on va utiliser un script qui va rechercher les bibliothèques pour nous et créer l'arborescence des répertoires :

Fichier: chroot.sh
#!/bin/bash
# Utilisation: $0 <chroot_path> <program list>
rep="$1"
shift

# Copie $1 vers $2 en créant les répertoires parents.
copie_dir ()
{
	[ -e "${2}" ] && return
 	rep_base=$(dirname "${2}")
 	[ -d "${rep_base}" ] || {
 		echo "++ mkdir -p ${rep_base}"
 		mkdir -p "${rep_base}"
 	}
 	echo "+ cp -a $1 $2"
 	cp -a "$1" "$2"
}
 
# Copie $1 vers $2 + copie des bibliothèques utilisées.
copie_ldd ()
{
	local src dest file f f_link
 	src="$1"
 	dest="$2"
 	[ -e "${dest}" ] && return
 	file=( $(ldd "$src" | awk '{print $3}' | grep '^/') )
 	file=( "${file[@]}" $(ldd "$src" | grep '/' | grep -v '=>' | awk '{print $1}') )
 	for f in "${file[@]}"
 	do
 		f_link=$(readlink -f "$f")
 		copie_dir "$f_link" "${rep}${f}"
 	done
 	copie_dir "$src" "${dest}"
}
 
for prog in "$@"
do
 	prog=$(which "$prog")
 	prog_real=$(readlink -f "$prog")
 	copie_ldd "$prog_real" "${rep}${prog}"	
done

Créons le répertoire où sera notre environnement chroot, et copions-y un minimum d'outils:

# cd /home
# mkdir chroot_env
# ./chroot.sh chroot_env bash /bin/bash bash ls cp mv rm cat more mkdir touch
++ mkdir -p chroot_env/lib
+ cp -a /lib/libreadline.so.6.0 chroot_env/lib/libreadline.so.6
+ cp -a /lib/libhistory.so.6.0 chroot_env/lib/libhistory.so.6
+ cp -a /lib/libncursesw.so.5.7 chroot_env/lib/libncursesw.so.5
+ cp -a /lib/libdl-2.10.1.so chroot_env/lib/libdl.so.2
+ cp -a /lib/libc-2.10.1.so chroot_env/lib/libc.so.6
+ cp -a /lib/ld-2.10.1.so chroot_env/lib/ld-linux.so.2
++ mkdir -p chroot_env/bin
+ cp -a /bin/bash chroot_env/bin/bash
+ cp -a /lib/librt-2.10.1.so chroot_env/lib/librt.so.1
+ cp -a /lib/libcap.so.2.17 chroot_env/lib/libcap.so.2
+ cp -a /lib/libacl.so.1.1.0 chroot_env/lib/libacl.so.1
+ cp -a /lib/libpthread-2.10.1.so chroot_env/lib/libpthread.so.0
+ cp -a /lib/libattr.so.1.1.0 chroot_env/lib/libattr.so.1
+ cp -a /bin/ls chroot_env/bin/ls
+ cp -a /bin/cp chroot_env/bin/cp
+ cp -a /bin/mv chroot_env/bin/mv
+ cp -a /bin/rm chroot_env/bin/rm
+ cp -a /bin/cat chroot_env/bin/cat
+ cp -a /bin/more chroot_env/bin/more
+ cp -a /bin/mkdir chroot_env/bin/mkdir
+ cp -a /bin/touch chroot_env/bin/touch

Il ne reste plus qu'à lancer le chroot:

# chroot chroot_env
bash-4.2# ls
bin  lib
bash-4.2# exit

Cas concret: ssh

Ce genre d'environnement peut être utilisé moyennement un minimum de modifications comme environnement minimal pour un serveur ssh. En supposant que vous avez un serveur ssh fonctionnel, et un utilisateur nommé test, modifiez l'environnement comme suit:

mkdir chroot_env/dev
cp -a /dev/{null,zero,stdin,stdout,stderr,{u,}random,tty} chroot_env/dev
mkdir chroot_env/home/test


Puis, modifiez le fichier /etc/ssh/sshd_config en y rajoutant:

Fichier: /etc/ssh/sshd_config
Match User test
 	ChrootDirectory /home/chroot_env/

Si vous lancez ssh en tant que service, redémarrez le :

systemctl restart sshd.service

Puis:

$ ssh test@localhost
test@localhost's password: 
Last login: Tue Oct 13 01:11:14 2009 from localhost.localdomain
-bash-4.0$ pwd
/home/test
-bash-4.0$ ls /bin   
bash  cat  cp  ls  mkdir  more	mv  rm  touch

Arch, système de base

On peut être amené à vouloir une Arch en bonne et due forme pour l'utiliser avec chroot, voici quelques exemples montrant comment y parvenir :

Minimum

Pour l'exemple, installons une base i686 avec comme dossier racine de notre environnement /opt/arch32. Il nous faut y créer une arborescence de base :

mkdir -p /opt/arch32/var/{cache/pacman/pkg,lib/pacman}

Créons un pacman.conf minimal et temporaire :

Fichier: /opt/arch32/pacman.conf
[options]
Architecture = i686
[core]
Server = http://mir.archlinux.fr/$repo/os/$arch
[extra]
Server = http://mir.archlinux.fr/$repo/os/$arch
[community]
Server = http://mir.archlinux.fr/$repo/os/$arch

Il n'y a plus qu'à lancer un pacman :

pacman --root /opt/arch32 \
       --cachedir /opt/arch32/var/cache/pacman/pkg \
       --config /opt/arch32/pacman.conf \
       -Sy bash coreutils filesystem grep gzip licenses sed pacman file

Votre système de base est installé, vous pouvez supprimer le pacman.conf temporarire :

rm /opt/arch32/pacman.conf

N'oubliez pas de configurer le chroot en activant un miroir (/opt/arch32/etc/pacman.d/mirrorlist) et en modifiant la directive Architecture dans /opt/arch32/etc/pacman.conf :

Fichier: /opt/arch32/pacman.conf
#...
[options]
#...
Architecture = i686
#...

Vous pouvez l'utiliser :

mount -t procfs proc /opt/arch32/proc
mount -t sysfs sys /opt/arch32/sys
mount -B {,/opt/arch32}/dev
mount -B {,/opt/arch32}/dev/pts
chroot /opt/arch32

Une fois quiité, il faut démonter dans le sens inverse :

umount /opt/arch32/{dev/pts,dev,sys,proc}


Utilisation de mkarchroot

Pour un système complet et une utilisation régulière, il peut être fastidieux de monter / démonter les différents système. Heureusement, on peut utiliser les outils livrés avec la distribution pour automatiser tout ça:

pacman -S devtools

Ce qui nous fournit l'outil mkarchroot qui permet de créer, mettre à jour et même configurer l'environnement de chroot, pour mener ceci à bien, il nous suffit de lui indiquer un pacman.conf et un répertoire de base.

Pour l'exemple, on va prendre un pacman.conf pointant vers des dépôts en 32bits, ce qui donnera un environnement 32 même pour les utilisateurs de 64bits, créons donc un pacman.conf dans /root:

Fichier: /root/pacman.conf
[options]
Architecture = i686
SigLevel = Never
[core]
Server = http://mir.archlinux.fr/$repo/os/$arch
[extra]
Server = http://mir.archlinux.fr/$repo/os/$arch
[community]
Server = http://mir.archlinux.fr/$repo/os/$arch

Puis création de l'environnement :

mkarchroot -C /root/pacman.conf /home/chroot_env base

Afin de compléter un environnement, un minimum de données doivent être reprises dans l'environnement chrooté, mkarchroot le fait automatiquement :

# linux32 mkarchroot -r bash /home/chroot_env
[root@archtest /]# uname -m
i686

mkarchroot reprend en plus /var/cache/pacman qui n'est pas nécessaire mais qui permet si vous êtes sur un environnement de même architecture de ne pas télécharger une deuxième fois les paquets lors d'installation dans le chroot.

Liens