tuto4 ready
This commit is contained in:
parent
b5de41662b
commit
e928733d61
17 changed files with 789 additions and 203 deletions
|
|
@ -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 à
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue