Journal UML est vivant

Posté par  (site web personnel) . Licence CC By‑SA.
36
14
mai
2021

Sommaire

Salut Nal,

Il y a longtemps, bien longtemps, les solutions de virtualisation libres sous Linux n'étaient pas bien nombreuses.
Pas de kvm, docker, lxc ou podman et qemu en était à ses débuts.

Il existait des solutions légères comme linux-vservers et openvz mais qui nécessitaient un patch du noyau Linux (pour la petite histoire, il s'agissait de solutions qui aujourd'hui entreraient dans la catégorie conteneurs).

Si tu avais de la chance, ta distribution fournissait des noyaux patchés (c'était le cas de la Debian par exemple), mais sinon tu avais droit à une recompilation du noyau.

C'est là que "user mode linux" entrait en jeu, car il te permettait de tester ton noyau fraîchement compilé sans avoir à l'installer sur une machine physique au risque de la voir se planter au démarrage.

"User Mode Linux" ou plus simplement UML c'était à l'époque un noyau Linux patché qui pouvait être lancé comme un exécutable standard dans un système existant.
On lui fournissait une image de système de fichier pour qu'il puisse démarrer un système (plus ou moins) complet, dans l'espace utilisateur, et ce sans privilèges particuliers.

D'abord conçu pour tester les noyaux, il était aussi possible de l'utiliser comme solution de virtualisation.

En terme de performance, il était bien en-dessous des solutions type conteneurs comme openvz, mais meilleur que des solutions de virtualisation pure telle que qemu ou bochs.

Je me suis récemment lancé dans la construction d'un système minimaliste avec buildroot et je me suis demandé comment tester ce système au fur et à mesure de sa progression.

J'aurai bien évidemment pu utiliser kvm, mais en cherchant un peu j'ai vu que UML était toujours bien vivant, et qu'en plus la Debian fournissait un noyau précompilé.
En plus buildroot semblait capable de générer un système de fichier tel que UML devrait pouvoir le gérer.

Alignement de planètes, il fallait que j'essaie.

Création du rootfs avec buildroot

Le but est d'avoir un système Linux minimaliste en utilisant notamment busybox.
buildroot permet de générer un tel système non seulement pour l'architecture sur laquelle il lancé, mais également pour d'autres architectures, pour les raspberry PI par exemple.

Il automatise la mécanique de compilation croisée nécessaire à la création d'un tel système tout en intégrant la possibilité d'installer toute un série de logiciels.

On commence par télécharger et extraire la version stable de buildroot (la 2021-02-2 au moment ou j'écris ceci).

wget https://buildroot.org/downloads/buildroot-2021.02.2.tar.gz
tar xzf buildroot-2021.02.2.tar.gz
cd buildroot-2021.02.2/

Pour fonctionner, il est indispensable d'installer un certain nombre de dépendances:

sudo apt install build-essential libncurses-dev unzip rsync bc

La première étape consiste à configurer la cible que l'on désire générer.
Pour cela buildroot propose un menu très détaillé lorsque l'on passe la commande make menuconfig.

Pour un premier essai, j'ai configuré les éléments suivants:

  • Target options -> Target Architecture (x86_64)
  • Filesystem images -> [*] ext2/3/4 root filesystem -> ext2/3/4 variant (ext4)

Il est maintenant possible de générer l'image du système avec make, mais attention cela va prendre un peu de temps et de disque.
Si tu as plusieurs coeurs (de processeurs) disponibles, tu peux utiliser l'option -j<n> pour lancer n constructions parallèles histoire de réduire le temps de compilation.

make -j2

A la fin du processus l'image générée est output/images/rootfs.ext4.

User Mode Linux

Le site officiel peut facilement laisser penser que le projet est moribond.
Il faut fouiller un peu plus pour voir que depuis un bon moment UML est intégré au noyau Linux standard.

On trouve dans la documentation des noyaux récents une section dédiée à UML bien plus à jour et utile.

La version Buster de Debian fournit un noyau UML pré-compilé et correspondant au noyau de la distribution.
Pour l'installer il suffit d'un apt install user-mode-linux.

Le paquet fourni donc l'exécutable /usr/bin/linux ainsi qu'une série de modules pour ce noyau dans /usr/lib/uml/modules.

Pour lancer notre système il nous suffit de passer la commande suivante:

linux mem=256M ubd0=output/images/rootfs.ext4 umid=test
Core dump limits :
        soft - 0
        hard - NONE
Checking that ptrace can change system call numbers...OK
Checking syscall emulation patch for ptrace...OK
Checking advanced syscall emulation patch for ptrace...OK
...
Run /sbin/init as init process
random: fast init done
EXT4-fs (ubda): re-mounted. Opts: (null)
Starting syslogd: OK
Starting klogd: OK
Running sysctl: OK
Initializing random number generator: OK
Saving random seed: random: dd: uninitialized urandom read (512 bytes read)
OK
Starting network: OK

Welcome to Buildroot
buildroot login: root
# 

Voilà, tu viens de lancer un système Linux/busybox en tant qu'utilisateur non privilégié et tu peux t'amuser en tant que root dans ce système.

Si ça ne fonctionne pas tu auras l'occasion pour une fois de faire un:

killall linux

Un point intéressant est que tu peux facilement avoir accès au système de fichier de l'hôte grâce à hostfs.
Par exemple pour monter dans ton UML le répertoire utilisateur de l'hôte:

mount -t hostfs -o /home/passke hostfs /mnt
mount
/dev/root on / type ext4 (rw,relatime)
devtmpfs on /dev type devtmpfs (rw,relatime,mode=755)
proc on /proc type proc (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,gid=5,mode=620,ptmxmode=666)
tmpfs on /dev/shm type tmpfs (rw,relatime,mode=777)
tmpfs on /tmp type tmpfs (rw,relatime)
tmpfs on /run type tmpfs (rw,nosuid,nodev,relatime,mode=755)
sysfs on /sys type sysfs (rw,relatime)
hostfs on /mnt type hostfs (rw,relatime,/home/passke)

Le noyau de ton UML ne peut pour l'instant pas charger de modules, le répertoire /lib/modules étant vide.
Mais comme cité plus haut, la Debian fournit les modules nécessaires sur l'hôte dans /usr/lib/uml/modules et il suffit donc de le monter au bon endroit:

mkdir /lib/modules
mount -t hostfs -o /usr/lib/uml/modules/ hostfs /lib/modules
modprobe loop
loop: module loaded

Compilation d'un noyau Linux en mode user

Pour l'instant on a utilisé le paquet fourni par la distribution, mais on peut également compiler un noyau récent en mode user assez facilement.

La première étape consiste assez classiquement à télécharger et extraire une version du noyau à partir de kernel.org.

wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.12.4.tar.xz
tar xJf linux-5.12.4.tar.xz
cd linux-5.12.4/

Puis on installe quelques dépendances:

sudo apt install flex bison

D'habitude pour configurer un noyau on utilise le fichier de configuration fourni par la distribution (dans /boot sur Debian).

Pour UML, c'est un peu différent, on commence par générer une nouvelle configuration en précisant qu'il s'agit d'une architecture um (=user mode).
Puis le reste du processus est identique à la compilation d'un noyau classique, excepté qu'il faut systématiquement préciser l'architecture um.

make defconfig ARCH=um
make menuconfig ARCH=um
make ARCH=um

Le processus devrait avoir généré un fichier exécutable linux à la racine des sources, et on peut donc maintenant lancer notre UML avec un noyau plus récent:

./linux mem=256M ubd0=../buildroot-2021.02.2/output/images/rootfs.ext4 umid=test

Initializing random number generator: OK
Saving random seed: random: dd: uninitialized urandom read (512 bytes read)
OK
Starting network: OK

Welcome to Buildroot
buildroot login: root
# uname -a
Linux buildroot 5.12.4 #1 Fri May 14 15:13:12 CEST 2021 x86_64 GNU/Linux

Pour l'instant par de modules du noyau disponbiles, on va arranger ça vite fait (sur l'hôte):

export INSTALL_MOD_PATH=../modules
make modules_install ARCH=um

On peut maintenant les utiliser dans l'UML:

mount -t hostfs -o /home/passke/modules/lib/modules hostfs /lib/modules
modprobe loop
loop: module loaded

Je vais m'arrêter là, mais il y a encore plein de choses à expérimenter, le réseau par exemple.
De ce côté, même si la configuration reste un peu complexe, elle a quand même bien évolué.

UML peut être intéressant par exemple pour faire de la virtualisation sur des machines ne disposant pas du support kvm, ou alors pour expérimenter des fonctionnalités offertes par les noyaux récents, eBPF par exemple ou alors construire des images sans avoir besoin des droits root sur le système hôte.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.