web-dev-qa-db-fra.com

Pourquoi est-ce que mon initrd n'a qu'un seul répertoire, à savoir le "noyau"?

J'utilise Debian Live-Build-Build pour travailler sur un système amorçable. À la fin du processus, je reçois les fichiers typiques utilisés pour démarrer un système en direct: un fichier SquashFs, certains GRUB modules et fichiers de configuration et un fichier initrd.img.

Je peux démarrer très bien en utilisant ces fichiers, en passant l'intite au noyau via

initrd=/path/to/my/initrd.img

sur la ligne de commande de bootloader. Mais quand j'essaie d'examiner le contenu de mon image InitiDrd, comme si:

$file initrd.img
initrd.img: ASCII cpio archive (SVR4 with no CRC)
$mkdir initTree && cd initTree
$cpio -idv < ../initrd.img

l'arbre de fichier que je reçois ressemble à ceci:

$tree --charset=ASCII
.
`-- kernel
    `-- x86
        `-- microcode
            `-- GenuineIntel.bin

Où est l'arborescence du système de fichiers, avec le typique/corbeille,/etc,/sbin ... contenant les fichiers réels utilisés pendant la démarrage?

30
user986730

La méthode de saut de bloc CPIO donné ne fonctionne pas de manière fiable. C'est parce que les images d'initiation que je me plaisaient n'avaient pas les deux archives concaténées sur une limite de 512 octets.

Fais cela:

apt-get install binwalk
legolas [mc]# binwalk initrd.img 
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             ASCII cpio archive (SVR4 with no CRC), file name: "kernel", file name length: "0x00000007", file size: "0x00000000"
120           0x78            ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86", file name length: "0x0000000B", file size: "0x00000000"
244           0xF4            ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86/microcode", file name length: "0x00000015", file size: "0x00000000"
376           0x178           ASCII cpio archive (SVR4 with no CRC), file name: "kernel/x86/microcode/GenuineIntel.bin", file name length: "0x00000026", file size: "0x00005000"
21004         0x520C          ASCII cpio archive (SVR4 with no CRC), file name: "TRAILER!!!", file name length: "0x0000000B", file size: "0x00000000"
21136         0x5290          gzip compressed data, from Unix, last modified: Sat Feb 28 09:46:24 2015

Utilisez le dernier numéro (21136) qui ne figure pas sur une limite de 512 octets pour moi:

legolas [mc]# dd if=initrd.img bs=21136 skip=1 | gunzip | cpio -tdv | head
drwxr-xr-x   1 root     root            0 Feb 28 09:46 .
drwxr-xr-x   1 root     root            0 Feb 28 09:46 bin
-rwxr-xr-x   1 root     root       554424 Dec 17  2011 bin/busybox
lrwxrwxrwx   1 root     root            7 Feb 28 09:46 bin/sh -> busybox
-rwxr-xr-x   1 root     root       111288 Sep 23  2011 bin/loadkeys
-rwxr-xr-x   1 root     root         2800 Aug 19  2013 bin/cat
-rwxr-xr-x   1 root     root          856 Aug 19  2013 bin/chroot
-rwxr-xr-x   1 root     root         5224 Aug 19  2013 bin/cpio
-rwxr-xr-x   1 root     root         3936 Aug 19  2013 bin/dd
-rwxr-xr-x   1 root     root          984 Aug 19  2013 bin/dmesg
33
Marc Merlin

Si vous connaissez votre initrd.img consiste en une archive CPIO non compressée, suivie d'une archive CPIO compressée GZ, vous pouvez utiliser ce qui suit pour extraire tous les fichiers (à partir des deux archives) dans votre répertoire de travail actuel (testé dans Bash):

(cpio -id; zcat | cpio -id) < /path/to/initrd.img

La ligne de commande ci-dessus transmet le contenu de initrd.img En tant qu'entrée standard dans un sous-groupe qui exécute les deux commandes cpio -id et zcat | cpio -id séquentiellement. La première commande (cpio -id) se termine une fois que cela a lu toutes les données appartenant à la première archive CPIO. Le contenu restant est ensuite transmis à zcat | cpio -id, qui décompresse et déballe la deuxième archive.

24
woolpool

Il s'avère généré par la construction en direct de Debian (et à ma surprise acceptée par le noyau) est en réalité la concaténation de deux images:

  • une archive CPIO contenant des mises à jour du microcode à appliquer sur le processeur;
  • une archive CPIO GZIP-ED, qui contient en réalité l'arborescence de fichiers InitiDRD (avec les répertoires/etc/bin/sbin/dev ... les annuaires attendus).

Lors de l'extraction de l'initial InitiDRD.IMG, hors sortie de la sortie en direct, j'ai reçu cette sortie:

$cpio -idv ../initrd.img
kernel
kernel/x86
kernel/x86/microcode
kernel/x86/microcode/GenuineIntel.bin
896 blocks

Ce qui signifie que l'extraction CPIO s'est terminée après avoir analysé 896 blocs de 512 octets chacun. Mais l'initial Initird.img était beaucoup plus grand que 896 * 512 = 458752B = 448 Ko:

$ls -liah initrd.img
3933924 -r--r--r-- 1 root root 21M Oct 21 10:05 initrd.img

Donc, l'image initiative réelle que je cherchais a été ajoutée juste après la première archive CPIO (celle contenant les mises à jour du microcode) et peut être consulté à l'aide de DD:

$dd if=initrd.img of=myActualInitrdImage.img.gz bs=512 skip=896
20
user986730

Basé sur l'idée donnée dans la réponse de @ Woolpool, j'ai écrit une fonction récursive qui fonctionnera pour toutes les archives CPIO, quel que soit l'arrangement des données concaténées et ne nécessite aucun outil spécial tel que Binwalk. Par exemple, mes mkinitramfs produisaient un CPIO; CPIO; fichier gzip. Cela fonctionne en extrayant chaque partie du fichier initial concaténé, enregistrant le reste dans un temp ... à l'aide du programme "Fichier" pour décider quoi faire avec la partie suivante.

uncpio(){
if [[ $(wc -c $1 | cut -d ' ' -f1) -eq 0 ]]; then
    return
fi

type=$(cat $1 | file -)
local tmpfile=$(date +%s.%N)
echo -e "\n$type"
if [[ $type =~ .*cpio.* ]]; then
    cat $1 | (cpio -id; cat >$tmpfile)
Elif [[ $type =~ .*gzip.* ]]; then
    zcat $1 | (cpio -id; cat >$tmpfile)
else
    return
fi
uncpio $tmpfile 
rm $tmpfile
}

Pour utiliser Type: UNCPIO InitiDRDFileName

2
SurpriseDog

Vous pouvez utiliser unmkinitramfs des outils Inititramfs> = 0,126, qui est inclus depuis Debian 9 (Stretch) et Ubuntu 18.04 (Bionic).

2
Benjamin Drung

Si vous avez besoin d'exécuter cette tâche souvent, vous pouvez créer une petite fonction Bash comme ci-dessous (et peut-être peut-être l'ajouter à votre fichier .bstrucc):

initramfs-extract() {
    local target=$1
    local offset=$(binwalk -y gzip $1 | awk '$3 ~ /gzip/ { print $1; exit }')
    shift
    dd if=$target bs=$offset skip=1 | zcat | cpio -id --no-absolute-filenames $@
}

Le code est basé sur la réponse de Marc, mais cela est nettement plus rapide puisque Binwalk ne recherchera que des fichiers GZIP. Vous pouvez l'invoquer, comme ceci:

$ initramfs-extract /boot/initrd.img -v

Vous aurez besoin de binwalk installé pour le faire fonctionner.

1
tyrion