tuto4 ready

This commit is contained in:
nemunaire 2022-11-11 10:14:16 +01:00
commit e928733d61
17 changed files with 789 additions and 203 deletions

View file

@ -1,5 +1,3 @@
\newpage
Le *namespace* `PID` {#pid-ns}
--------------------
@ -23,13 +21,92 @@ trouve.
Première étape s'isoler :
<div lang="en-US">
```bash
```
42sh# unshare --pid --fork /bin/bash
inpidns# echo $$
1
```
</div>
Nous utilisons ici l'option `-f`, pour que le passage dans le nouvel espace de
noms des PID soit effectif (cf. [Introduction](#pid-ns-intro)).
::::: {.question}
#### Qu'est-ce qu'il se passe sans l'option `--fork` ? {-}
\
Nous utilisons ici l'option `--fork`, pour que le passage dans le nouvel espace
de noms des PID soit effectif (cf. [Introduction](#pid-ns-intro)). Si on
l'omet, voici ce qu'il se passe :
<div lang="en-US">
```
42sh# unshare --pid /bin/sh
inpidns# echo $$
23456
```
</div>
Ce n'est apparemment pas ce que l'on souhaitait : on est toujours dans l'ancien
*namespace*, puisqu'on a juste `unshare(2)`, sans `fork(2)`. Si l'on va plus
loin et que l'on `fork` en demandant à `sh` d'exécuter un nouveau processus :
<div lang="en-US">
```
42sh# unshare --pid /bin/sh
inpidns# echo $$
34567
inpidns# sh
inpidns# echo $$
1
```
</div>
C'est d'ailleurs le bon moment pour regarder le contenu de notre fichier
`pid_for_children` pour le processus `34567` :
<div lang="en-US">
```
42sh# ls -l /proc/34567/ns/pid*
lrwxrwxrwx 1 nemunaire 1 oct. 23:42 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 nemunaire 1 oct. 23:42 pid_for_children -> 'pid:[4026532993]'
```
</div>
On remarque bien que l'on se trouve dans un entre-deux : `pid` pointe toujours
sur l'*inode* de l'arbre de PID initial, tandis que `pid_for_children` est prêt
à transmettre le nouvel *inode* aux nouveaux processus.
\
#### Pourquoi ça ne fonctionne pas du tout avec `bash` ? {-}
\
Si on utilise `bash` à la place de `sh` dans les exemples précédents, toujours
sans l'option `--fork`, on obtient une erreur plutôt étrange :
<div lang="en-US">
```
42sh# unshare --pid /bin/bash
inpidns# echo $$
65432
inpidns# sh
-bash: fork: Cannot allocate memory
```
</div>
Il se trouve que `bash` commence par `fork(2)` lui-même afin de réaliser un
certain nombre d'opérations. Notre PID 1, le premier PID de notre conteneur, a
donc été alloué à un processus d'initialisation de `bash`, qui s'est terminé
depuis.\
Le comportement du noyau, lorsque le PID 1 se termine, est de lancer un *kernel
panic* (car c'est un processus indispensable, notamment de part son rôle de
parent pour tous les processus orphelin). Au sein d'un *namespace* `PID` qui
n'est pas le *namespace* racine, le noyau appelle la fonction
`disable_pid_allocation` qui retire le *flag* `PIDNS_HASH_ADDING` de l'espace
de nom. Le fait de ne pas avoir `PIDNS_HASH_ADDING` fait retourner `ENOMEM` à
la fonction `alloc_pid` appelée par `fork(2)` et `clone(2)`. On n'a donc pas
d'autre choix que de quitter ce *namespace* pour en recréer un nouveau.
:::::
Un coup d'œil à `top` ou `ps aux` devrait nous montrer que l'on est maintenant
le seul processus ... pourtant, il n'en est rien, ces deux commandes continuent
@ -45,12 +122,12 @@ notre système initial. Pour s'en sortir, il est nécessaire de s'isoler dans un
*namespace* `mount` séparé.
#### Double isolation : ajout du *namespace* `mount`
### Double isolation : ajout du *namespace* `mount`
Voici la nouvelle ligne de commande que l'on va utiliser :
<div lang="en-US">
```bash
```
42sh# unshare --pid --mount --fork --mount-proc /bin/bash
```
</div>
@ -90,11 +167,11 @@ de noms.
[^PR_SET_CHILD_SUBREAPER]: en réalité, ce comportement est lié à la propriété
`PR_SET_CHILD_SUBREAPER`, qui peut être définie pour n'importe quel processus
de l'arborescence. Le processus au PID 1 hérite forcément de cette propriété\ ;
de l'arborescence. Le processus au PID 1 hérite forcément de cette propriété ;
il va donc récupérer tous les orphelins, si aucun de leurs parents n'a la
propriété définie.
Lorsque l'on lance un processus via `nsenter(1)` ou `setns(2)`, cela crée un
Lorsqu'on lance un processus via `nsenter(1)` ou `setns(2)`, cela crée un
processus qui n'est sans doute pas un fils direct du processus d'`init` de
notre conteneur. Malgré tout, même s'il est affiché comme n'étant pas un fils à
l'extérieur du conteneur, les propriétés d'`init` sont biens appliquées à