Dans la première partie, nous avons découvert le fonctionnement de base de Yocto. Nous avons réussi à produire et tester des images pour différentes plateformes. Toutefois nous n’avons absolument rien modifié au contenu de l’image. Dans cette nouvelle partie nous allons personnaliser notre système embarqué. Pour la plupart des constructions dans les séquences à venir nous emploierons une cible Arm émulée par Qemu pour la simplicité des tests et des captures d’écran. Néanmoins les opérations décrites ici seront adaptables sur n’importe quelle carte supportée par Yocto.
Débutons donc cette séquence avec la commande :
[Yocto-lab]$ source layers/poky/oe-init-build-env builds/build-qemu [...] [build-qemu]$
Jusqu’à présent nous avons très peu modifié le fichier
conf/local.conf
, il est temps de l'examiner un
peu plus en détail.
local.conf
Nous allons faire plusieurs modification dans ce fichier. Ultérieurement nous créerons notre propre image pour regrouper notre configuration de manière plus réutilisable et plus facile à versionner indépendamment du build de Yocto.
J’ai l’habitude de regrouper les modifications que j’apporte à
«local.conf
» vers le début de ce fichier en
les encadrant clairement pour pouvoir identifier facilement mes
actions. En voici un exemple :
[...] # <LOGILIN> MACHINE = "qemuarm" DL_DIR = "${TOPDIR}/../../downloads" SSTATE_DIR = "${TOPDIR}/../../sstate-cache" # </LOGILIN> [...]
Bien sûr dès que la complexité des modifications dépasse quelques
lignes, il devient préférable de les suivre par l’intermédiaire
d’un système de gestion de versions comme git
.
Les variables que nous avons déjà modifiées dans le chapitre précédent :
MACHINE
: comme on l’a vu
dans la séquence précédente, ceci permet de sélectionner la
plateforme cible. Ici, une émulation de carte ARM par Qemu.
Le contenu de cette variable doit correspondre au nom d'un fichier
d'extension .conf
placé dans un sous-dossier
conf/machine/
d'un layer parcouru par bitbake.
Dans notre cas, il s'agit de
Yocto-lab/layers/poky/meta/conf/machine/qemuarm.conf
.
DL_DIR
: lorsque Yocto
télécharge des packages de fichiers sources pour les
compiler, il les stocke dans ce répertoire en vérifiant au
préalable s’ils n’ont pas déjà été chargés. Par défaut il
s’agit du sous-dossier «dowloads/
»
dans le répertoire de compilation (variable
TOPDIR
). J’ai inséré ici
«../../
» pour remonter le répertoire de
stockage des fichiers téléchargés deux crans au-dessus, à côté de
layers/
et de builds/
. L’intérêt
sera de conserver ce répertoire pour le mettre en commun avec
d’autres builds pour d’autres cibles.
SSTATE_DIR
: comme
DL_DIR
, il s’agit d’un répertoire de stockage.
Lorsque Yocto progresse dans ses compilations il stocke des
fichiers temporaires, des fichiers objets, etc. dans ce
dossier. Il peut ensuite les retrouver pour accélérer (très
sensiblement) les builds suivants. Comme précédemment,
j’ai remonté le répertoire de «../../
»
par rapport à sa situation par défaut pour le partager avec
d'autres builds éventuels.
BB_NUMBER_THREADS
. Yocto est très
gourmand. Autant en place mémoire ou disque qu'en ressource
CPU. Lorsqu'un build s'exécute, tous les coeurs de
processeur sont sollicités à 100%. Si on doit utiliser la
machine de compilation pour un autre travail pendant la
compilation, le système va manquer sérieusement de fluidité. On
peut donc restreindre le nombre de jobs que
bitbake
lance simultanément pour le rendre moins
agressif, en indiquant par exemple
«BB_NUMBER_THREADS="8"
» pour se
limiter à huit jobs en parallèle au prix d'un allongement
inévitable du temps de compilation.
Nous pouvons relancer une génération d’image avec :
[build-qemu]$ bitbake core-image-base
La cible «core-image-base
» est un peu plus
riche que «core-image-minimal
» que nous avons
employée dans les séquences précédentes. Une fois la compilation
terminée, on démarre l’émulateur avec :
[build-qemu]$ runqemu
La première différence avec l’image minimale est l’apparition d’un splashscreen, une barre de progression graphique pendant le démarrage comme nous le voyons sur la figure II.1-1.
Le nombre de services démarrés au boot semble également un peu plus important qu’auparavant :
Poky (Yocto Project Reference Distro) 5.0.2 qemuarm /dev/ttyAMA0 qemuarm login: root WARNING: Poky is a reference Yocto Project distribution that should be used for testing and development purposes only. It is recommended that you create your own distribution for production use. root@qemuarm:~# ps PID USER VSZ STAT COMMAND 1 root 1604 S init [5] 2 root 0 SW [kthreadd] 3 root 0 SW [pool_workqueue_] 4 root 0 IW< [kworker/R-rcu_g] 5 root 0 IW< [kworker/R-rcu_p] 6 root 0 IW< [kworker/R-slub_] 7 root 0 IW< [kworker/R-netns] 8 root 0 IW [kworker/0:0-eve] 9 root 0 IW [kworker/0:1-eve] 10 root 0 IW< [kworker/0:0H-kb] 11 root 0 IW [kworker/u8:0-ev] 12 root 0 IW [kworker/u8:1] 13 root 0 IW< [kworker/R-mm_pe] 14 root 0 IW [rcu_tasks_kthre] 15 root 0 IW [rcu_tasks_rude_] 16 root 0 IW [rcu_tasks_trace] 17 root 0 SW [ksoftirqd/0] 18 root 0 IW [rcu_preempt] 19 root 0 SW [migration/0] 20 root 0 SW [cpuhp/0] 21 root 0 SW [cpuhp/1] 22 root 0 SW [migration/1] 23 root 0 SW [ksoftirqd/1] 24 root 0 IW [kworker/1:0-mm_] 25 root 0 IW< [kworker/1:0H-kb] 26 root 0 SW [cpuhp/2] 27 root 0 SW [migration/2] 28 root 0 SW [ksoftirqd/2] 29 root 0 IW [kworker/2:0-rcu] 30 root 0 IW< [kworker/2:0H-kb] 31 root 0 SW [cpuhp/3] 32 root 0 SW [migration/3] 33 root 0 SW [ksoftirqd/3] 34 root 0 IW [kworker/3:0-eve] 35 root 0 IW< [kworker/3:0H-ev] 36 root 0 IW [kworker/u9:0-ev] 37 root 0 IW [kworker/u10:0-w] 38 root 0 IW [kworker/u11:0-e] 39 root 0 IW [kworker/u12:0-e] 40 root 0 SW [kdevtmpfs] 41 root 0 IW< [kworker/R-inet_] 42 root 0 IW [kworker/2:1-eve] 43 root 0 IW [kworker/u9:1-ev] 44 root 0 SW [oom_reaper] 45 root 0 IW [kworker/u11:1-e] 46 root 0 IW< [kworker/R-write] 47 root 0 SW [kcompactd0] 48 root 0 IW< [kworker/R-crypt] 49 root 0 IW< [kworker/R-kbloc] 50 root 0 IW< [kworker/R-blkcg] 51 root 0 IW [kworker/u12:1-e] 52 root 0 IW [kworker/3:1-eve] 53 root 0 IW< [kworker/R-md] 54 root 0 IW< [kworker/R-md_bi] 55 root 0 SW [watchdogd] 56 root 0 IW [kworker/u10:1] 57 root 0 IW< [kworker/3:1H-kb] 58 root 0 IW< [kworker/R-rpcio] 59 root 0 IW< [kworker/R-xprti] 60 root 0 SW [kswapd0] 61 root 0 IW< [kworker/R-nfsio] 62 root 0 IW< [kworker/R-cifsi] 63 root 0 IW< [kworker/R-smb3d] 64 root 0 IW< [kworker/R-cifsf] 65 root 0 IW< [kworker/R-cifso] 66 root 0 IW< [kworker/R-defer] 67 root 0 SW [hwrng] 68 root 0 IW [kworker/1:1-mm_] 69 root 0 IW< [kworker/R-raid5] 70 root 0 IW< [kworker/R-dm_bu] 71 root 0 IW< [kworker/R-mld] 72 root 0 IW< [kworker/R-ipv6_] 75 root 0 IW< [kworker/u13:0] 76 root 0 IW< [kworker/u14:0] 77 root 0 IW< [kworker/u15:0] 78 root 0 IW< [kworker/u16:0] 79 root 0 IW< [kworker/u17:0] 80 root 0 SW [jbd2/vda-8] 81 root 0 IW [kworker/3:2-eve] 82 root 0 IW< [kworker/R-ext4-] 84 root 0 IW [kworker/3:3-eve] 85 root 0 IW< [kworker/1:1H-kb] 88 root 0 IW< [kworker/2:1H-kb] 101 root 0 IW< [kworker/0:1H-kb] 125 root 5284 S /sbin/udevd -d 145 root 0 IW [kworker/u11:2] 296 messageb 2080 S /usr/bin/dbus-daemon --system 301 rpc 1736 S /usr/sbin/rpcbind 315 root 2360 S /sbin/syslogd -n -O /var/log/messages 318 root 2360 S /sbin/klogd -n 326 avahi 2424 S avahi-daemon: running [qemuarm.local] 327 avahi 2316 S avahi-daemon: chroot helper 336 root 2360 S {start_getty} /bin/sh /bin/start_getty 115200 ttyAMA0 vt102 337 root 1448 S /usr/sbin/ttyrun hvc0 /bin/start_getty 115200 hvc0 vt102 338 root 2360 S /sbin/getty 38400 tty1 340 root 2388 S -sh 343 root 2388 R ps root@qemuarm:~#
Comme auparavant nous pouvons nous connecter sous l’identité
«root
» sans mot de passe.
Ceci est évidemment très dérangeant pour des raisons de sécurité :
sudo
» pour
passer des commandes nécessitant les privilèges de
l’administrateur. Si l’on tolère la connexion avec l’identité
root, il faut au moins qu’elle soit protégée par un mot
de passe solide.
Nous souhaitons donc fixer un mot de passe pour l’administrateur
root (par exemple «linux
») et créer un
compte utilisateur standard, disons «guest
»,
avec le mot de passe «welcome
».
Bien évidemment ces mots de passe sont des exemples typiques de ce qu’il ne faut pas faire. Ils existent dans des dictionnaires et sont suffisamment courts pour être trouvés par force brute. Un bon mot de passe est un mot de passe long et facile à mémoriser (par exemple une association de plusieurs mots sans cohérence entre eux). Inutile de mélanger des lettres majuscules, minuscules et des chiffres, ça n’ajoute que très peu d’entropie à la chaîne de caractères. À mon avis, la meilleure explication est celle de Randall Munroe sur son site XKCD :
Pour ajouter un utilisateur standard et modifier le mot de passe de
root nous allons intervenir dans le fichier
«local.conf
». Tout d’abord nous devons ajouter
une ligne un peu énigmatique :
INHERIT += "extrausers"
Elle indique simplement que notre configuration va pouvoir utiliser les
services d’une classe définie dans Poky permettant la personnalisation
des utilisateurs. On notera la syntaxe «+=
»
pour indiquer que la chaîne de caractères
«extrausers
» est ajoutée à la liste des
classes contenues dans la variable «INHERIT
».
Pour créer un nouveau compte utilisateur on ajoutera une ligne
qui configure le comportement de la classe extrausers
comme celle-ci :
EXTRA_USERS_PARAMS += "useradd -p '<password>' <username>;"
On ajoute (+=
) ainsi une commande (useradd
)
dans la variable de paramétrage de la classe extrausers
.
Plusieurs commandes peuvent être enchaînées, elles sont séparées par un
point-virgule.
La commande «useradd
» appelée n’est pas celle
du système («/usr/sbin/useradd
» sur la plupart
des distributions) mais est fournie par Poky dans l’ensemble des outils
du système de développement.
Jusqu'à la version Hardknott de Poky (avril 2021), il était
possible de fournir le mot de passe en clair. L'option à utiliser pour
useradd
était -P
. Depuis la version
Honister (octobre 2021) cette possibilité a disparue pour des
raisons de sécurité. Nous devons nécessairement utiliser l'option
-p
et fournir le mot de passe haché.
Pour hacher le mot de passe, nous avons plusieurs possibilités. La
plus simple est d'employer la commande openssl
présente
sur la majorité des distributions Linux :
[build-qemu]$ openssl passwd -5 welcome $5$eKqF9xI8OoXR3ZLR$zIefp3eQ6EDjV/sEESJf04XiuGr.QQs/WoTZy/QMTu3 [build-qemu]$
Le hachage utilisé est SHA256 mais il est possible si on
le souhaite de préférer SHA512 en précisant l'option
-6
au lieu de -5.
Le résultat du hachage est la chaîne affichée par openssl
.
Elle contient trois parties séparées par les caractères
«$
» :
$5$
, indique le type de
hachage (ici SHA256) ;$eKqF9xI8OoXR3ZLR$
, est une chaîne
aléatoire insérée devant le mot de passe avant le hachage, afin
d'ajouter une part d'indéterminisme et d'augmenter la
sécurité (c'est ce qui fait qu'en répétant la commande ci-dessus on a
toujours un résultat différent), on l'appelle habituellement le «grain de
sel» ;$zIefp3eQ6EDjV/sEESJf04XiuGr.QQs/WoTZy/QMTu3
, est le
résultat du hachage.
Il faudra donc prendre toute la ligne de résultat et la copier dans
la commande useradd
ci-dessus. Néanmoins cela n'est pas
suffisant, il faut également préfixer les caractères
«$
» par des «\
».
En reprenant notre example précédent, nous devons ajouter dans le fichier
conf/local.conf
:
EXTRA_USERS_PARAMS += "useradd -p '\$5\$eKqF9xI8OoXR3ZLR\$zIefp3eQ6EDjV/sEESJf04XiuGr.QQs/WoTZy/QMTu3' guest;"
Nous pouvons ajouter un mot de passe pour root en invoquant la
commande «usermod
». Tout d'abord nous
calculons le hachage :
[build-qemu]$ openssl passwd -5 linux $5$VVkW56RF8jYiBDze$5v1V.z8wUkCL00T9.MNTsA4iAGyqk1.IaYq/hUMKnM1
Puis nous copions ce résultat dans la ligne usermod
,
sans oublier de précéder les «$
» de
«\
» :
EXTRA_USERS_PARAMS += "usermod -p '\$5\$VVkW56RF8jYiBDze\$5v1V.z8wUkCL00T9.MNTsA4iAGyqk1.IaYq/hUMKnM1' root;"
Mon fichier «local.conf
» devient donc :
# <LOGILIN> MACHINE = "qemuarm" DL_DIR = "${TOPDIR}/../../downloads" SSTATE_DIR = "${TOPDIR}/../../sstate-cache" INHERIT += "extrausers" EXTRA_USERS_PARAMS += "useradd -p '\$5\$eKqF9xI8OoXR3ZLR\$zIefp3eQ6EDjV/sEESJf04XiuGr.QQs/WoTZy/QMTu3' guest;" EXTRA_USERS_PARAMS += "usermod -p '\$5\$VVkW56RF8jYiBDze\$5v1V.z8wUkCL00T9.MNTsA4iAGyqk1.IaYq/hUMKnM1' root;" # </LOGILIN> [...]
Attention à ne pas oublier d'encadrer le mot de passe par des quotes simples (apostrophes) et l'ensemble de la chaîne par des quotes doubles (guillemets).
Si nous relançons le build, nous pouvons tester nos connexions au bout de quelques dizaines de secondes :
Poky (Yocto Project Reference Distro) 5.0.2 qemuarm /dev/ttyAMA0 qemuarm login: root Password: (linux) WARNING: Poky is a reference Yocto Project distribution that should be used for testing and development purposes only. It is recommended that you create your own distribution for production use. root@qemuarm:~# whoami root root@qemuarm:~# exit Poky (Yocto Project Reference Distro) 5.0. qemuarm /dev/ttyAMA0 qemuarm login: guest Password: (welcome) WARNING: Poky is a reference Yocto Project distribution that should be used for testing and development purposes only. It is recommended that you create your own distribution for production use. qemuarm:~$ whoami guest qemuarm:~$ su - Password: (linux) root@qemuarm:~# whoami root root@qemuarm:~# exit qemuarm:~$ exit Poky (Yocto Project Reference Distro) 5.0.2 qemuarm /dev/ttyAMA0
Avant de connaître l'usage de la sous-commande passwd
et openssl
, j'avais développé un petit utilitaire
permettant de hacher un mot de passe. Cet outil peut s'avérer
intéressant si on souhaite automatiser la saisie et la copie du
résultat dans le fichier conf/local.conf
, car il
dispose d'une option «-e
» (pour
«escape») qui préfixe automatiquement les
«$
» par des «\
».
En voici un petit exemple d'installation et d'utilisation :
[build-qemu]$ git clone https://github.com/cpb-/password-encryption Cloning into 'password-encryption'... remote: Enumerating objects: 98, done. remote: Counting objects: 100% (56/56), done. remote: Compressing objects: 100% (40/40), done. remote: Total 98 (delta 27), reused 41 (delta 14), pack-reused 42 Receiving objects: 100% (98/98), 25.40 KiB | 5.08 MiB/s, done. Resolving deltas: 100% (46/46), done. [build-qemu]$ cd password-encryption/ [password-encryption (master)]$ make cc -Wall -W -D_HASHER_VERSION=1.0.1 -c hasher.c cc -o hasher hasher.o -lcrypt
On peut hacher un mot de passe simplement ainsi :
[password-encryption]$ ./hasher linux $5$p4pbIZkJ$rdM34E4hsys2v5vSUnj6mbd9jcLQSzKH59rDDDWhvxC
Pour que les «$
» soient précédés
automatiquement par des «\
», on ajoute :
[password-encryption]$ ./hasher -e linux \$5\$IlhPmUHu\$AFPAiidalJ5Llt5YSqKoKXUbiWJjbvtRYT0AvzJp6p7 [password-encryption]$ ./hasher -e welcome \$5\$gFkqOeNU\$BOtEK2RhJIu.MxFT4jqtaYGYdw85fiRbc4hplRWI/63 [password-encryption]$ cd .. [build-qemu]$
Une seconde étape de personnalisation, toujours dans le fichier
«local.conf
» concerne le nom de la machine.
Visible dans le prompt il vaut par défaut
«qemuarm
». Nous pouvons le personnaliser en
ajoutant la ligne suivante dans
«local.conf
» :
hostname:pn-base-files = "mybox"
La syntaxe de cette ligne est plus complexe qu’elle en a l’air.
Lorsque bitake
analyse les recettes et les fichiers de
configuration, il lit cette ligne ainsi : «Lors du
traitement de la recette dont le nom de package (pn
pour
Package Name) est base-files
, configurer la
variable hostname
avec la valeur
mybox
».
En règle générale, dans une affectation de variable, le caractère
«deux-points»
«:
» permet de préciser ou
restreindre la portée de l’opération.
La chaîne de caractères «:pn
»
peut être imaginée comme une sorte d’opérateur pour restreindre la
modification de l’affectation de la variable à la recette dont le nom
est «base-files
».
Dans les versions Hardknott et antérieures de Poky, le
caractère «deux-points» était remplacé par le caractère
«souligné» (underscore)
«_
».
Comme son nom l’indique, la recette
«base-files
», livrée avec Poky, fournit un
ensemble de fichiers de configuration standards comme
/etc/fstab
, /etc/host.conf
,
/etc/shells
, etc. En outre elle fournit des méthodes pour
personnaliser hostname
, et proposer un message de
bienvenue «Poky (Yocto Project Reference Distro) 5.0.2 qemuarm
/dev/ttyAMA0» avant l’invite de connexion.
Ce message peut être modifié en surchargeant le fichier par défaut, nous le ferons dans une prochaine étape.
Après recompilation, la connexion au système affiche :
Poky (Yocto Project Reference Distro) 5.0.2 mybox /dev/ttyAMA0 mybox login: root Password: (linux) WARNING: Poky is a reference Yocto Project distribution that should be used for testing and development purposes only. It is recommended that you create your own distribution for production use. root@mybox:~#
Le message indiquant que Poky est une distribution destinée au test et qu'il vaut mieux écrire sa propre distro pour un système en production est apparu avec la branche Scarthgap de Yocto. Nous verrons dans une prochaine séquence comment écrire notre configuration de distro et nous affranchir de ce message.
Nous avons édité dans cette séquence le fichier
«local.conf
» se trouvant dans le sous-dossier
«conf/
» du répertoire de compilation. Pour le
moment nous avons simplement configuré les utilisateurs (et mots de
passe) et le nom de machine, dès la prochaine séquence nous allons
ajouter des utilitaires dans notre système embarqué.
Si vous préférez une session de cours interactif, en mode présentiel ou distanciel, n'hésitez pas à vous inscrire à mes formations "Développeur Linux embarqué avec Yocto Project" ou "Yocto Project avancé" .
Ce document est placé sous licence Creative Commons CC BY-NC. Vous pouvez copier son contenu et le réemployer à votre gré pour une utilisation non-commerciale. Vous devez en outre mentionner sa provenance.
Le nom Yocto Project est une marque déposée par la Linux Foundation. Le présent document n'est en aucune façon approuvé par Yocto Project ou la Linux Foundation.