2021-10-31 19:51:17 +00:00
|
|
|
|
\newpage
|
|
|
|
|
|
2022-04-09 00:50:14 +00:00
|
|
|
|
Les espaces de noms -- *namespaces*
|
2021-10-31 19:51:17 +00:00
|
|
|
|
===================================
|
|
|
|
|
|
|
|
|
|
Nous avons vu un certain nombre de fonctionnalités offertes par le noyau Linux
|
|
|
|
|
pour limiter, autoriser ou contraindre différents usages des ressources de
|
|
|
|
|
notre machine.
|
|
|
|
|
|
|
|
|
|
Ces fonctionnalités sont très utiles pour éviter les dénis de service, mais nos
|
|
|
|
|
processus ne sont pas particulièrement isolés du reste du système. On aimerait
|
|
|
|
|
maintenant que nos processus n'aient pas accès à l'ensemble des fichiers, ne
|
2022-11-11 09:14:16 +00:00
|
|
|
|
puissent pas interagir avec les autres processus, avoir leur propre pile
|
2021-10-31 19:51:17 +00:00
|
|
|
|
réseau, ... Voyons maintenant les *namespaces* qui vont nous permettre de faire
|
|
|
|
|
cela.
|
|
|
|
|
|
|
|
|
|
|
2022-11-11 09:14:16 +00:00
|
|
|
|
Présentation des *namespaces*
|
|
|
|
|
-----------------------------
|
2021-10-31 19:51:17 +00:00
|
|
|
|
|
|
|
|
|
Les espaces de noms du noyau, que l'on appelle *namespaces*, permettent de
|
|
|
|
|
dupliquer certaines structures, habituellement considérées uniques pour le
|
2022-11-11 09:14:16 +00:00
|
|
|
|
noyau, dans le but qu'un groupe de processus soit isolé d'autres processus, sur
|
|
|
|
|
certains aspects de l'environnement dans lequel il s'exécute.
|
2021-10-31 19:51:17 +00:00
|
|
|
|
|
2022-02-24 19:43:43 +00:00
|
|
|
|
On en dénombre huit (le dernier ayant été ajouté dans Linux 5.6) : `cgroup`,
|
2021-10-31 19:51:17 +00:00
|
|
|
|
`IPC`, `network`, `mount`, `PID`, `time`, `user` et `UTS`.
|
|
|
|
|
|
|
|
|
|
La notion d'espace de noms est relativement nouvelle et a été intégrée
|
|
|
|
|
progressivement au sein du noyau Linux. Aussi, toutes les structures ne sont
|
2022-02-24 19:43:43 +00:00
|
|
|
|
pas encore *containerisables* : le document fondateur[^NSDOC] parle ainsi
|
2021-10-31 19:51:17 +00:00
|
|
|
|
d'isoler les journaux d'événements ou encore les modules de sécurité (LSM, tels
|
|
|
|
|
que AppArmor, SELinux, Yama, ...).
|
|
|
|
|
|
|
|
|
|
[^NSDOC]: <https://www.kernel.org/doc/ols/2006/ols2006v1-pages-101-112.pdf>
|
|
|
|
|
|
2022-11-11 09:14:16 +00:00
|
|
|
|
Commençons par passer en revue rapidement les différents *namespaces*.
|
2021-10-31 19:51:17 +00:00
|
|
|
|
|
|
|
|
|
#### L'espace de noms `mount` {.unnumbered #mount-ns}
|
|
|
|
|
|
|
|
|
|
Depuis Linux 2.4.19.
|
|
|
|
|
|
2022-11-11 09:14:16 +00:00
|
|
|
|
Cet espace de noms dissocie la liste des points de montage.
|
2021-10-31 19:51:17 +00:00
|
|
|
|
|
|
|
|
|
Chaque processus appartenant à un *namespace mount* différent peut monter,
|
|
|
|
|
démonter et réorganiser à sa guise les points de montage, sans que cela n'ait
|
|
|
|
|
d'impact sur les processus hors de cet espace de noms. Une partition ne sera
|
|
|
|
|
donc pas nécessairement démontée après un appel à `umount(2)`, elle le sera
|
|
|
|
|
lorsqu'elle aura effectivement été démontée de chaque *namespace mount* dans
|
|
|
|
|
lequel elle était montée.
|
|
|
|
|
|
2022-11-11 09:14:16 +00:00
|
|
|
|
Il s'agit d'une version améliorée de nos bons vieux `chroot`, puisqu'il n'est
|
|
|
|
|
plus possible de s'en échapper en remontant l'arborescence.
|
|
|
|
|
|
2021-10-31 19:51:17 +00:00
|
|
|
|
|
|
|
|
|
#### L'espace de noms `UTS` {.unnumbered #uts-ns}
|
|
|
|
|
|
|
|
|
|
Depuis Linux 2.6.19.
|
|
|
|
|
|
|
|
|
|
Cet espace de noms isole le nom de machine et son domaine NIS.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### L'espace de noms `IPC` {.unnumbered #ipc-ns}
|
|
|
|
|
|
|
|
|
|
Depuis Linux 2.6.19.
|
|
|
|
|
|
|
|
|
|
Cet espace de noms isole les objets IPC et les files de messages POSIX.
|
|
|
|
|
|
|
|
|
|
Une fois le *namespace* attaché à un processus, il ne peut alors plus parler
|
|
|
|
|
qu'avec les autres processus de son espace de noms (lorsque ceux-ci passent par
|
|
|
|
|
l'API IPC du noyau).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### L'espace de noms `PID` {.unnumbered}
|
|
|
|
|
|
|
|
|
|
Depuis Linux 2.6.24.
|
|
|
|
|
|
|
|
|
|
Cet espace de noms isole la liste des processus et virtualise leurs numéros.
|
|
|
|
|
|
|
|
|
|
Une fois dans un espace, le processus ne voit que le sous-arbre de processus
|
|
|
|
|
également attachés à son espace. Il s'agit d'un sous-ensemble de l'arbre global
|
2022-02-24 19:43:43 +00:00
|
|
|
|
de PID : les processus de tous les PID *namespaces* apparaissent donc dans
|
2021-10-31 19:51:17 +00:00
|
|
|
|
l'arbre initial.
|
|
|
|
|
|
|
|
|
|
Pour chaque nouvel espace de noms de processus, une nouvelle numérotation est
|
|
|
|
|
initiée. Ainsi, le premier processus de cet espace porte le numéro 1 et aura
|
2022-02-24 19:43:43 +00:00
|
|
|
|
les mêmes propriétés que le processus `init` usuel\ ; entre autres, si un
|
2021-10-31 19:51:17 +00:00
|
|
|
|
processus est rendu orphelin dans ce *namespace*, il devient un fils de ce
|
|
|
|
|
processus, et non un fils de l'`init` de l'arbre global.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### L'espace de nom `network` {.unnumbered}
|
|
|
|
|
|
|
|
|
|
Depuis Linux 2.6.29.
|
|
|
|
|
|
|
|
|
|
Cet espace de noms fournit une isolation pour toutes les ressources associées
|
2022-02-24 19:43:43 +00:00
|
|
|
|
aux réseaux : les interfaces, les piles protocolaires IPv4 et IPv6, les tables
|
2021-10-31 19:51:17 +00:00
|
|
|
|
de routage, règles pare-feu, ports numérotés, etc.
|
|
|
|
|
|
|
|
|
|
Une interface réseau (`eth0`, `wlan0`, ...) ne peut se trouver que dans un seul
|
|
|
|
|
espace de noms à la fois. Il est par contre possible de les déplacer.
|
|
|
|
|
|
|
|
|
|
Lorsque le *namespace* est libéré (généralement lorsque le dernier processus
|
|
|
|
|
attaché à cet espace de noms se termine), les interfaces qui le composent sont
|
|
|
|
|
ramenées dans l'espace initial/racine (et non pas dans l'espace parent, en cas
|
|
|
|
|
d'imbrication).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### L'espace de noms `user` {.unnumbered}
|
|
|
|
|
|
|
|
|
|
Depuis Linux 3.8.
|
|
|
|
|
|
|
|
|
|
Cet espace de noms isole la liste des utilisateurs, des groupes, leurs
|
|
|
|
|
identifiants, les *capabilities*, la racine et le trousseau de clefs du noyau.
|
|
|
|
|
|
|
|
|
|
La principale caractéristique est que les identifiants d'utilisateur et de
|
|
|
|
|
groupe pour un processus peuvent être différents entre l'intérieur et
|
|
|
|
|
l'extérieur de l'espace de noms. Il est donc possible, alors que l'on est un
|
|
|
|
|
simple utilisateur à l'extérieur du *namespace*, d'avoir l'UID 0 dans le
|
|
|
|
|
conteneur.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### L'espace de noms `cgroup` {.unnumbered #cgroup-ns}
|
|
|
|
|
|
|
|
|
|
Depuis Linux 4.6.
|
|
|
|
|
|
|
|
|
|
Cet espace de noms filtre l'arborescence des *Control Group* en changeant la
|
|
|
|
|
racine vue par le processus. Au sein d'un *namespace* `cgroup`, la racine vue
|
|
|
|
|
correspond en fait à un sous-groupe de l'arborescence globale.
|
|
|
|
|
|
|
|
|
|
Ainsi, un processus dans un *CGroup* *namespace* ne peut pas voir le contenu
|
|
|
|
|
des sous-groupes parents (pouvant laisser fuiter des informations sur le reste
|
|
|
|
|
du système). Cela peut également permettre de faciliter la migration de
|
2022-02-24 19:43:43 +00:00
|
|
|
|
processus (d'un système à un autre) : l'arborescence des *cgroups* n'a alors
|
2021-10-31 19:51:17 +00:00
|
|
|
|
plus d'importance car le processus ne voit que son groupe.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#### L'espace de noms `time` {.unnumbered #time-ns}
|
|
|
|
|
|
|
|
|
|
Depuis Linux 5.6.
|
|
|
|
|
|
|
|
|
|
Avec cet espace de noms, il n'est pas possible de virtualiser l'heure d'un de
|
|
|
|
|
nos conteneurs (on peut seulement changer le fuseau horaire, puisqu'ils sont
|
2022-11-11 09:14:16 +00:00
|
|
|
|
gérés par la `libc`). Les horloges virtualisées avec ce *namespace* sont les
|
2021-10-31 19:51:17 +00:00
|
|
|
|
compteurs `CLOCK_MONOTONIC` et `CLOCK_BOOTTIME`.
|
|
|
|
|
|
|
|
|
|
Lorsque l'on souhaite mesurer un écoulement de temps, la méthode naïve consiste
|
|
|
|
|
à enregistrer l'heure au départ de notre opération, puis à faire une
|
|
|
|
|
soustraction avec l'heure de fin. Cette technique fonctionne bien, à partir du
|
|
|
|
|
moment où l'on est sûr que l'horloge ne remontera pas dans le temps, parce
|
|
|
|
|
qu'elle se synchronise ou que le changement d'heure été/hiver
|
|
|
|
|
intervient, ... Pour palier ces situations imprévisibles, le noyau expose une
|
|
|
|
|
horloge dite monotone (`CLOCK_MONOTONIC`) : cette horloge démarre à un entier
|
|
|
|
|
abstrait et s'incrèmente chaque seconde qui passe, sans jamais sauter de
|
|
|
|
|
secondes, ni revenir en arrière. C'est une horloge fiable pour calculer des
|
|
|
|
|
intervalles de temps.
|
|
|
|
|
|
|
|
|
|
De la même manière `CLOCK_BOOTTIME` mesure le temps qui s'écoule, mais prend en
|
|
|
|
|
compte les moments où la machine est en veille (alors que `CLOCK_MONOTONIC` ne
|
|
|
|
|
compte que les moments où la machine est en éveil).
|
|
|
|
|
|
|
|
|
|
Étant donné l'usage de ces deux horloges, en cas de migration d'un processus
|
|
|
|
|
d'une machine à une autre, il convient de recopier l'état des horloges
|
|
|
|
|
monotones qu'il utilise, afin que ses calculs ne soient pas chamboulés.
|