Si tout comme moi vous souhaitez faire de la programmation bas niveau, il vous faudra un jour ou l’autre comprendre comment fonctionne le noyau Linux.
Dans ce post je vais donc expliquer comment compiler puis installer un noyau Linux pour faire du kernel debugging et tout pleins de choses cool.

Pré-requis :

  • Une distribution Linux pour compiler le kernel
  • GCC, make, git, libncurses5-dev, bc
  • Savoir dompter la ligne de commande

Si vous n’avez pas de machine de test à utiliser ou que vous avez peur d’endomager la partie hardware, je vous conseille de passer par une machine virtuelle (VM) avec Virtual Box.
J’ai eu quelques problèmes avec VMware lors de l’installation des initramfs.
Dans mon cas je vais utiliser un vieux MAcBook de 2008 qui tourne sous Ubuntu 16.04 x86_64.

Préparation

Dans un premier temps il faut récuperer les fichiers source du noyau. Si vous êtes un aventurier vous pouvez les récuperer directement sur la branche Master de Github : git clone https://github.com/torvalds/linux
Sinon vous allez récuperer une version stable depuis kernel.org.

Dans notre cas on va prendre la dernière version stable à ce jour : 4.11.8
$ wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.11.8.tar.xz
Puis nous désarchivons l’archive contenant les sources du noyau Linux 4.11.8.
$ tar Jxvf linux-4.11.8.tar.xz
Enfin rendez-vous dans le repertoire de Linux : cd linux-4.11.8.

Compilation

Nous somme maintenant dans le repertoire du kernel que nous allons utiliser.

Assurez-vous d’avoir bien installé tous les outils dans les pré-requis.

Nous allons premièrement créer un fichier .config qui enregistre toutes les options de compilation du noyau. Pour ce faire lancez la commande make defconfig.
L’option defconfig permet de générer un fichier de configuration par défaut pour l’architecture de votre processeur.

$ make defconfig
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
*** Default configuration is based on 'x86_64_defconfig'
#
# configuration written to .config
#

Puis nous allons modifier les options de compilation du Makefile. Lancez un make menuconfig.

$ make menuconfig
  HOSTCC  scripts/kconfig/mconf.o
  HOSTCC  scripts/kconfig/lxdialog/checklist.o
  HOSTCC  scripts/kconfig/lxdialog/util.o
  HOSTCC  scripts/kconfig/lxdialog/inputbox.o
  HOSTCC  scripts/kconfig/lxdialog/textbox.o
  HOSTCC  scripts/kconfig/lxdialog/yesno.o
  HOSTCC  scripts/kconfig/lxdialog/menubox.o
  HOSTLD  scripts/kconfig/mconf
scripts/kconfig/mconf  Kconfig

Vous devriez avoir une interface ncurses comme ceci : menuconf

Pour ma part il faut que j’ajoute quelques drivers pour le trackpad de mon Macbook
mcdrivers

Je vais aussi demander la compilation du kernel avec KGDB pour le kernel debugging en activant les options que ceci : kgdb

N’hésitez pas à tester des options pour la compilation du noyau sur votre VM.

Dès que vous avez configuré comme bon vous semble le fichier .config nous pouvons lancer la compilation avec make.
Pour gagner du temps j’utilise tous les coeurs de mon processeur pour effectuer plusieurs jobs à la fois ce qui permet au Makefile de compiler n objets à la fois (n = nombre de coeurs).
Vous pouvez utiliser la commande nproc pour vous assurer du nombre de coeurs que vous avez à votre disposition

$ nproc
2

Dans mon cas je n’ai que 2 coeurs sur ma machine. Lançons la compilation comme ceci :

$ make -j $(nproc)
scripts/kconfig/conf  --silentoldconfig Kconfig
  SYSTBL  arch/x86/entry/syscalls/../../include/generated/asm/syscalls_32.h
  CHK     include/config/kernel.release
  UPD     include/config/kernel.release
  WRAP    arch/x86/include/generated/asm/clkdev.h
  WRAP    arch/x86/include/generated/asm/dma-contiguous.h
  WRAP    arch/x86/include/generated/asm/early_ioremap.h
  WRAP    arch/x86/include/generated/asm/mcs_spinlock.h
  WRAP    arch/x86/include/generated/asm/mm-arch-hooks.h
  CHK     include/generated/uapi/linux/version.h
  UPD     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  UPD     include/generated/utsrelease.h
  CC      scripts/mod/empty.o
  HOSTCC  scripts/mod/mk_elfconfig
  [...]
   OBJCOPY arch/x86/boot/vmlinux.bin
  AS      arch/x86/boot/header.o
  LD      arch/x86/boot/setup.elf
  OBJCOPY arch/x86/boot/setup.bin
  BUILD   arch/x86/boot/bzImage
Setup is 15836 bytes (padded to 15872 bytes).
System is 10415 kB
CRC db999948
Kernel: arch/x86/boot/bzImage is ready  (#1)

En fonction de la configuration hardware de votre machine virtuelle ou physique cela peut prendre ou plus ou moins du temps.

Installation

Dès que la compilation est terminée nous pouvons installer les nouveaux modules :

$ sudo make modules_install 
  INSTALL drivers/input/mouse/appletouch.ko
  INSTALL drivers/input/mouse/bcm5974.ko
  INSTALL drivers/input/mouse/cyapatp.ko
  INSTALL drivers/input/mouse/sermouse.ko
  INSTALL drivers/thermal/x86_pkg_temp_thermal.ko
  INSTALL fs/efivarfs/efivarfs.ko
  INSTALL lib/crc-itu-t.ko
  INSTALL net/ipv4/netfilter/ipt_MASQUERADE.ko
  INSTALL net/ipv4/netfilter/iptable_nat.ko
  INSTALL net/ipv4/netfilter/nf_log_arp.ko
  INSTALL net/ipv4/netfilter/nf_log_ipv4.ko
  INSTALL net/ipv4/netfilter/nf_nat_ipv4.ko
  INSTALL net/ipv4/netfilter/nf_nat_masquerade_ipv4.ko
  INSTALL net/ipv6/netfilter/nf_log_ipv6.ko
  INSTALL net/netfilter/nf_log_common.ko
  INSTALL net/netfilter/nf_nat.ko
  INSTALL net/netfilter/nf_nat_ftp.ko
  INSTALL net/netfilter/nf_nat_irc.ko
  INSTALL net/netfilter/nf_nat_sip.ko
  INSTALL net/netfilter/xt_LOG.ko
  INSTALL net/netfilter/xt_addrtype.ko
  INSTALL net/netfilter/xt_mark.ko
  INSTALL net/netfilter/xt_nat.ko
  DEPMOD  4.11.8

Nous avons installé les nouveaux modules. Il ne nous reste plus qu’à générer un initrd pour notre noyau et installer le kernel et autres composants essentiels avec la commande make install :

$ sudo make install
sh ./arch/x86/boot/install.sh 4.11.8 arch/x86/boot/bzImage \
        System.map "/boot"
run-parts: executing /etc/kernel/postinst.d/apt-auto-removal 4.11.8 /boot/vmlinuz-4.11.8
run-parts: executing /etc/kernel/postinst.d/initramfs-tools 4.11.8 /boot/vmlinuz-4.11.8
update-initramfs: Generating /boot/initrd.img-4.11.8
run-parts: executing /etc/kernel/postinst.d/pm-utils 4.11.8 /boot/vmlinuz-4.11.8
run-parts: executing /etc/kernel/postinst.d/unattended-upgrades 4.11.8 /boot/vmlinuz-4.11.8
run-parts: executing /etc/kernel/postinst.d/update-notifier 4.11.8 /boot/vmlinuz-4.11.8
run-parts: executing /etc/kernel/postinst.d/zz-update-grub 4.11.8 /boot/vmlinuz-4.11.8
Generating grub configuration file ...
Warning: Setting GRUB_TIMEOUT to a non-zero value when GRUB_HIDDEN_TIMEOUT is set is no longer supported.
Found linux image: /boot/vmlinuz-5.9.0
Found initrd image: /boot/initrd.img-5.9.0
Found linux image: /boot/vmlinuz-4.11.8
Found initrd image: /boot/initrd.img-4.11.8
Found linux image: /boot/vmlinuz-4.9.0
Found initrd image: /boot/initrd.img-4.9.0
Found linux image: /boot/vmlinuz-4.9.0.old
Found initrd image: /boot/initrd.img-4.9.0
Found linux image: /boot/vmlinuz-4.4.0-72-generic
Found initrd image: /boot/initrd.img-4.4.0-72-generic
Found linux image: /boot/vmlinuz-4.4.0-38-generic
Found initrd image: /boot/initrd.img-4.4.0-38-generic
Found linux image: /boot/vmlinuz-4.4.0-21-generic
Found initrd image: /boot/initrd.img-4.4.0-21-generic
done

Ok tout est bon, pour appliquer le nouveau kernel à votre distribution Linux, il suffit de redemarrer avec la commande reboot en tant que root.

Pour vérifier l’application du nouveau noyau fraichement compilé on utilise la commande uname comme ceci :

$ uname -a
Linux kernel-dev 4.11.8 #1 SMP Sun Jul 2 12:04:58 EDT 2017 x86_64 x86_64 x86_64 GNU/Linux

On voit bien que les changements ont été appliqués car c’est bel et bien la version correspondant au noyau que nous avons récupéré sur kernel.org. Nous pouvons aussi comparer le date de compilation avec la date courante :

$ date
Sun Jul  2 12:12:32 EDT 2017

Celle-ci correspond bien, donc tout est bon.

Pour conclure, la compilation du noyau Linux et une étape importante à comprendre pour ensuite se lancer plus profondement dans la programmation kernel et bas niveau.
Si vous souhaitez en savoir plus sur le noyau Linux, je vous invite à jeter un oeil au Gitbook de 0xax : Linux Insides.
Ce E-Book gratuit explique les concepts du noyau, du démarrage de celui-ci à la gestion de mémoire en passant pas les Syscalls.

Si vous avez besoin d’infos contactez-moi sur twitter: @matteyeux 

Github : https://github.com/matteyeux