«« sommaire »»

II.1 – Personnalisation de la configuration

Christophe BLAESS - juillet 2023

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.

Fichier 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 :

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) 4.0.11 qemuarm /dev/ttyAMA0

qemuarm login: root

root@qemuarm:~# ps
  PID USER       VSZ STAT COMMAND
    1 root      1680 S    init [5]
    2 root         0 SW   [kthreadd]
    3 root         0 IW<  [rcu_gp]
    4 root         0 IW<  [rcu_par_gp]
    5 root         0 IW<  [slub_flushwq]
    6 root         0 IW<  [netns]
    7 root         0 IW   [kworker/0:0-rcu]
    8 root         0 IW<  [kworker/0:0H-kb]
    9 root         0 IW   [kworker/u8:0-ev]
   10 root         0 IW<  [mm_percpu_wq]
   11 root         0 SW   [rcu_tasks_kthre]
   12 root         0 SW   [rcu_tasks_rude_]
   13 root         0 SW   [rcu_tasks_trace]
   14 root         0 SW   [ksoftirqd/0]
   15 root         0 IW   [rcu_preempt]
   16 root         0 SW   [migration/0]
   17 root         0 SW   [cpuhp/0]
   18 root         0 SW   [cpuhp/1]
   19 root         0 SW   [migration/1]
   20 root         0 SW   [ksoftirqd/1]
   21 root         0 IW   [kworker/1:0-mm_]
   22 root         0 IW<  [kworker/1:0H-kb]
   23 root         0 SW   [cpuhp/2]
   24 root         0 SW   [migration/2]
   25 root         0 SW   [ksoftirqd/2]
   26 root         0 IW   [kworker/2:0-mm_]
   27 root         0 IW<  [kworker/2:0H-ev]
   28 root         0 SW   [cpuhp/3]
   29 root         0 SW   [migration/3]
   30 root         0 SW   [ksoftirqd/3]
   31 root         0 IW   [kworker/3:0-mld]
   32 root         0 IW<  [kworker/3:0H-kb]
   33 root         0 SW   [kdevtmpfs]
   34 root         0 IW<  [inet_frag_wq]
   35 root         0 IW   [kworker/0:1-eve]
   36 root         0 SW   [oom_reaper]
   37 root         0 IW<  [writeback]
   38 root         0 SW   [kcompactd0]
   54 root         0 IW<  [cryptd]
   72 root         0 IW<  [kblockd]
   73 root         0 IW<  [blkcg_punt_bio]
   74 root         0 IW   [kworker/1:1-eve]
   75 root         0 IW   [kworker/2:1-mm_]
   76 root         0 IW   [kworker/3:1-mm_]
   77 root         0 IW   [kworker/u8:1-ev]
   78 root         0 IW<  [md]
   79 root         0 SW   [watchdogd]
   80 root         0 IW<  [kworker/2:1H-kb]
   81 root         0 IW<  [rpciod]
   82 root         0 IW<  [kworker/u9:0]
   83 root         0 IW<  [xprtiod]
   84 root         0 IW   [kworker/u8:2]
  104 root         0 SW   [kswapd0]
  105 root         0 IW<  [nfsiod]
  106 root         0 IW<  [cifsiod]
  107 root         0 IW<  [smb3decryptd]
  108 root         0 IW<  [cifsfileinfoput]
  109 root         0 IW<  [cifsoplockd]
  110 root         0 IW<  [deferredclose]
  112 root         0 SW   [hwrng]
  113 root         0 IW<  [kworker/3:1H-kb]
  114 root         0 IW<  [raid5wq]
  115 root         0 IW<  [dm_bufio_cache]
  116 root         0 IW<  [mld]
  117 root         0 IW<  [ipv6_addrconf]
  130 root         0 IW<  [kworker/1:1H-kb]
  131 root         0 IW   [kworker/3:2-mm_]
  132 root         0 SW   [jbd2/vda-8]
  133 root         0 IW<  [ext4-rsv-conver]
  135 root         0 IW<  [kworker/0:1H-kb]
  136 root         0 IW   [kworker/3:3]
  171 root      2936 S    /sbin/udevd -d
  291 messageb  2640 S    /usr/bin/dbus-daemon --system
  296 rpc       1928 S    /usr/sbin/rpcbind
  313 root      2488 S    /sbin/syslogd -n -O /var/log/messages
  316 root      2488 S    /sbin/klogd -n
  324 avahi     3092 S    avahi-daemon: running [qemuarm.local]
  325 avahi     2984 S    avahi-daemon: chroot helper
  334 root      2488 S    {start_getty} /bin/sh /bin/start_getty 115200 ttyAMA0 vt102
  335 root      2488 S    /sbin/getty 38400 tty1
  337 root      2576 S    -sh
  340 root      2576 R    ps
root@qemuarm:~# 

Utilisateurs et mots de passe

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é :

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 mystérieuse :

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 semblable à 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 «$» :

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) 4.0.11 qemuarm /dev/ttyAMA0

qemuarm login: root
Password: (linux)
root@qemuarm:~# whoami
root
root@qemuarm:~# exit

Poky (Yocto Project Reference Distro) 4.0.11 qemuarm /dev/ttyAMA0

qemuarm login: guest
Password: (welcome)
qemuarm:~$ whoami
guest
qemuarm:~$ su -
Password: (linux)
root@qemuarm:~# whoami
root
root@qemuarm:~# exit
qemuarm:~$ exit

Poky (Yocto Project Reference Distro) 4.0.11 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]$ 

Hostname

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) 4.0.11 qemuarm /dev/tty1» 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) 4.0.11 mybox /dev/ttyAMA0

mybox login: root
Password: (linux)
root@mybox:~#

Conclusion

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é.

Ce document est placé sous licence Creative Common 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.

«« sommaire »»