Comment décompresser et lister le contenu d’un initramfs sous Linux
Supposons que nous ayons la configuration de notre système Linux avec un chiffrement de disque presque complet, avec seulement la partition /boot non chiffrée. En supposant que nous ayons obtenu le chiffrement en utilisant un conteneur LUKS, nous avons besoin du logiciel approprié pour le déverrouiller au démarrage. Ce logiciel, cependant, fait partie du système crypté. Depuis la série Linux 2.6, la solution à ce problème, et à d’autres problèmes similaires, s’appelle initramfs (Initial ramfs). Dans cet article, nous voyons comment un initramfs est composé et comment extraire ou lister son contenu.
Dans ce tutoriel, vous allez apprendre :
- Qu’est-ce qu’un initramfs
- Comment extraire/inspecter un initramfs avec des outils de base
- Comment lister le contenu d’un initramfs avec lsinitrd/lsinitramfs
- Comment extraire un contenu initramfs à l’aide de unmkinitramfs sur Debian
Configuration logicielle requise et conventions utilisées
Qu’est-ce qu’un initramfs ?
Nous avons vu le « pourquoi » d’un initramfs : rendre les logiciels et les modules du noyau nécessaires disponibles dès le début du démarrage. Mais qu’est-ce qu’un initramfs et où est-il stocké ? Un initramfs est essentiellement une archive cpio compressée. Normalement, il est stocké dans la partition /boot, avec l’image du noyau à laquelle il est associé, et nommé d’après (par exemple initramfs-5.14.14-300.fc35.x86_64.img). Dans certaines situations, il serait utile de savoir comment vérifier son contenu et/ou l’extraire. Voyons comment faire.
Comment inspecter et extraire un initramfs avec des outils de base
Que contient une archive initramfs ? Eh bien, nous savons comment créer et décompresser une archive cpio, alors essayons de le faire, et voyons si nous pouvons inspecter le contenu initramfs :
sudo cpio -ivF /boot/initramfs-5.14.14-300.fc35.x86_64.img
.
early_cpio
kernel
kernel/x86
kernel/x86/microcode
kernel/x86/microcode/GenuineIntel.bin
10 blocks
La commande ci-dessus est préfixée par sudo simplement parce que le fichier initramfs avec lequel je travaille, pour les besoins de ce tutoriel, sur Fedora, est possédé par root et a 600 comme permissions définies. Une fois la commande exécutée, les fichiers et répertoires suivants sont créés dans le répertoire de travail :
.
├── early_cpio
└── kernel
└── x86
└── microcode
└── GenuineIntel.bin
3 directories, 2 files
Tout ce qu’il y a, c’est essentiellement du microcode du noyau Intel. Est-ce tout ce qu’il y a à l’intérieur de l’initramfs ? En fait, ce n’est pas le cas. Si nous observons la sortie de la commande que nous avons exécutée dans l’exemple précédent, nous pouvons voir cpio arrêté après 10 blocs de 512 octets (5120 octets) ; Cependant, si nous vérifions la taille totale de l’archive, nous pouvons voir qu’elle est plus grande que cela :
sudo ls -l /boot/initramfs-5.14.14-300.fc35.x86_64.img
-rw-------. 1 root root 34594545 Nov 25 15:38 /boot/initramfs-5.14.14-300.fc35.x86_64.img
D’après la sortie de ls, nous pouvons voir que la taille totale de l’initramfs est de 34594545 octets. Qu’est-il arrivé au reste du contenu d’initramfs ? Parfois, comme dans ce cas, un initramfs peut être en fait composé de deux parties ou segments :
- Une première archive cpio, très petite et non compressée
- Une archive cpio compressée qui contient le contenu principal
Dans l’exemple précédent, nous avons extrait le contenu de la première petite archive cpio. Comment pouvons-nous extraire le contenu de la deuxième archive compressée qui contient le système de fichiers réel monté pendant les premières étapes du démarrage ? Tout d’abord, nous devons l’isoler.
Dans ce cas, nous savons que la première archive cpio est composée de 10 blocs de 512 octets, nous pouvons donc utiliser dd pour commencer la lecture à partir de ce moment-là, et enregistrer le résultat dans un fichier que nous appellerons main_archive. Nous pouvons y parvenir en utilisant l’option skip de dd, qui, comme son nom l’indique, nous permet de sauter le nombre donné de blocs de l’entrée (par défaut, chaque bloc est considéré comme étant de 512 octets). Nous gérons :
sudo dd if=/boot/initramfs-5.14.14-300.fc35.x86_64.img skip=10 of=main_archiveUne fois que dd a fini de fonctionner, nous trouverons le fichier main_archive créé dans notre répertoire de travail. Maintenant, ce que nous devons faire, c’est trouver quel type de compression a été utilisé pour cela. Nous pouvons le faire à l’aide de l’utilitaire de fichiers, qui dans ce cas renvoie le résultat suivant :
file main_archive
main_archive: gzip compressed data, max compression, from Unix, original size modulo 2^32 74156544
À partir de la sortie de la commande, nous pouvons clairement voir que le fichier a été compressé à l’aide de gzip. Maintenant, nous savons tout ce dont nous avons besoin pour décompresser et extraire l’archive cpio. Nous pouvons tout faire avec une seule commande et quelques tuyaux d’obus. Avant de le faire, créons un répertoire appelé initramfs_filesystem et extrayons tout le contenu de l’archive compressée à l’intérieur de celui-ci :
mkdir initramfs_filesystem
zcat main_archive | cpio -ivD initramfs_filesystem
Pour extraire l’archive dans un répertoire autre que le nôtre, comme vous pouvez le remarquer, nous avons utilisé l’option -D de la commande cpio, et passé le chemin du répertoire en argument. Une fois l’extraction effectuée, si nous jetons un coup d’œil au contenu initramfs extrait, nous pouvons voir qu’il ressemble au véritable système de fichiers racine :
ls initramfs_filesystem
bin dev etc init lib lib64 proc root run sbin shutdown sys sysroot tmp usr var
Que se passe-t-il si nous voulons simplement obtenir une liste des fichiers et répertoires contenus dans les initramfs sans les extraire ? Très simple. Nous pouvons exécuter cpio avec l’option -t :
zcat main_archive | cpio -t initramfs_filesystemLa commande ci-dessus produirait une sortie similaire à celle ci-dessous (tronquée) :
.
bin
dev
dev/console
dev/kmsg
dev/null
dev/random
dev/urandom
etc
etc/authselect
etc/authselect/nsswitch.conf
etc/block_uuid.map
etc/cmdline.d
etc/conf.d
etc/conf.d/systemd.conf
etc/crypttab
[...]
Inspecter ou extraire les initramfs de la manière dont nous l’avons fait ci-dessus peut être un peu fastidieux ; Heureusement, il existe des utilitaires spécifiques conçus pour obtenir les mêmes résultats. Jetons-y un coup d’œil.
Inspection de la teneur en initramfs avec lsinitrd/lsinitramfs
Dans la section précédente, nous avons vu comment extraire le contenu d’un initramfs et comment répertorier son contenu avec des outils simples comme gzip, cpio et dd. Pour faciliter ces processus, une série d’outils sont disponibles, en fonction de la distribution que nous utilisons.
Pour lister le contenu d’un initramfs, par exemple, on peut utiliser les scripts lsinitrd et lsinitramfs. Le premier est utilisé sur Fedora et la famille de distributions Red Hat, le second sur Debian et les distributions basées sur Debian. L’initrd est un peu trompeur, puisqu’un initrd était essentiellement ce qui était utilisé avant l’adoption d’initramfs, mais c’est ainsi. L’utilisation du script est vraiment simple. Nous l’invoquons et lui passons le chemin de l’image initramfs que nous voulons inspecter en argument :
sudo lsinitrd /boot/initramfs-5.14.14-300.fc35.x86_64.imgLe script produit une sortie qui inclut à la fois le contenu de l’archive cpio « early », non compressée, les modules dracut utilisés pour générer les initramfs (dracut est le programme utilisé pour créer les initramfs sur Fedora), et le contenu de l’archive cpio principale, compressée (la sortie est tronquée pour des raisons évidentes) :
Early CPIO image
========================================================================
drwxr-xr-x 3 root root 0 Oct 28 21:55 .
-rw-r--r-- 1 root root 2 Oct 28 21:55 early_cpio
drwxr-xr-x 3 root root 0 Oct 28 21:55 kernel
drwxr-xr-x 3 root root 0 Oct 28 21:55 kernel/x86
drwxr-xr-x 2 root root 0 Oct 28 21:55 kernel/x86/microcode
-rw-r--r-- 1 root root 4096 Oct 28 21:55 kernel/x86/microcode/GenuineIntel.bin
========================================================================
Version: dracut-055-6.fc35
Arguments: --kver '5.14.14-300.fc35.x86_64' -f
dracut modules:
systemd
systemd-initrd
systemd-sysusers
nss-softokn
dbus-broker
dbus
i18n
network-manager
network
ifcfg
drm
plymouth
crypt
dm
kernel-modules
kernel-modules-extra
kernel-network-modules
lvm
rootfs-block
terminfo
udev-rules
dracut-systemd
usrmount
base
fs-lib
shutdown
========================================================================
drwxr-xr-x 12 root root 0 Oct 28 21:55 .
crw-r--r-- 1 root root 5, 1 Oct 28 21:55 dev/console
crw-r--r-- 1 root root 1, 11 Oct 28 21:55 dev/kmsg
crw-r--r-- 1 root root 1, 3 Oct 28 21:55 dev/null
crw-r--r-- 1 root root 1, 8 Oct 28 21:55 dev/random
crw-r--r-- 1 root root 1, 9 Oct 28 21:55 dev/urandom
lrwxrwxrwx 1 root root 7 Oct 28 21:55 bin -> usr/bin
drwxr-xr-x 2 root root 0 Oct 28 21:55 dev
drwxr-xr-x 13 root root 0 Oct 28 21:55 etc
drwxr-xr-x 2 root root 0 Oct 28 21:55 etc/authselect
-rw-r--r-- 1 root root 2999 Oct 28 21:55 etc/authselect/nsswitch.conf
[...]
Le script lsinitramfs fonctionne fondamentalement de la même manière. Il fait partie du paquet « initramfs-tools-core » sur Debian, il n’est donc pas nécessaire de l’installer. Par défaut, il affiche simplement la liste des fichiers dans l’initramfs ; Toutefois, si l’option -l est utilisée, les autorisations de fichiers et de répertoires sont également signalées :
lsinitramfs -l /boot/initrd.img-5.10.0-8-amd64
drwxr-xr-x 7 root root 0 Dec 1 10:56 .
lrwxrwxrwx 1 root root 7 Dec 1 10:56 bin -> usr/bin
drwxr-xr-x 3 root root 0 Dec 1 10:56 conf
-rw-r--r-- 1 root root 16 Dec 1 10:56 conf/arch.conf
drwxr-xr-x 2 root root 0 Dec 1 10:56 conf/conf.d
-rw-r--r-- 1 root root 49 Dec 1 10:50 conf/conf.d/resume
-rw-r--r-- 1 root root 1365 Jan 14 2021 conf/initramfs.conf
[...]
Dépaquetage des initramfs avec umkinitramfs (Debian)
Pour extraire le contenu d’un initramfs sur Debian et les distributions basées sur Debian, nous pouvons utiliser le script unmkinitramfs, qui est suffisamment intelligent pour détecter si l’initramfs est composé de plusieurs archives cpio, comme celle que nous avons vue dans la première partie de ce tutoriel. Le script prend le chemin du fichier initramfs à extraire comme premier argument, et le chemin du répertoire où le contenu doit être extrait comme second. Pour extraire le fichier /boot/initrd.img-5.10.0-8-amd64 dans le répertoire de travail actuel, par exemple, nous exécuterions :
unmkinitramfs /boot/initrd.img-5.10.0-8-amd64 .Conclusions
Dans ce tutoriel, nous avons appris ce qu’est un initramfs et quel est son but sur les distributions Linux modernes. Nous avons vu comment il est parfois composé de deux archives cpio : la première, non compressée et très petite, qui contient généralement le microcode cpu, et la seconde, compressée, qui contient le reste du contenu (logiciels, modules du noyau etc...). Nous avons vu comment extraire un initramfs à l’aide d’outils de base et de scripts dédiés, et comment lister son contenu.
