diff --git a/tutorial/3/capabilities.md b/tutorial/3/capabilities.md
index d213ef8..d23be45 100644
--- a/tutorial/3/capabilities.md
+++ b/tutorial/3/capabilities.md
@@ -14,7 +14,7 @@ privilégiés outrepassaient ces tests, tandis que les autres devaient passer le
tests de l'*effective UID*, *effective GID*, et autres groupes
supplémentaires...
-Dans les années 90, ce système s'est rélévé être un peu trop basique et
+Dans les années 90, ce système s'est révélé être un peu trop basique et
conduisait régulièrement à des abus, au moyen de vulnérabilités trouvées dans
les programmes *setuid root*.
@@ -41,7 +41,7 @@ contient les hashs des mots de passe).
C'est ainsi qu'est apparu le `suid-bit` parmi les modes de fichiers. Lorsque
ce bit est défini sur un binaire exécutable, au moment de l'exécution, le
contexte passe à celui du propriétaire du fichier (`root` si le propriétaire
-est `root`, mais cela fonctionne quelque soit le propriétaire du fichier : on
+est `root`, mais cela fonctionne quel que soit le propriétaire du fichier : on
ne devient pas `root`, mais bien l'utilisateur propriétaire).\
@@ -158,7 +158,7 @@ Tout d'abord, il faut noter que chaque *thread* dispose de 5 ensembles de
- ***inheritable*** (I) : est utilisé au moment de la résolution des *capabilities*
lors de l'exécution d'un nouveau processus. Il s'agit des *capabilities* qui
- seront transmises au processus fil. À moins d'avoir la *capability*
+ seront transmises au processus fils. À moins d'avoir la *capability*
`CAP_SETPCAP`, cet ensemble ne peut pas avoir plus de *capability* que celles
présentent dans l'ensemble *permitted* ;
@@ -209,7 +209,7 @@ intervenir et par exemple les ACL POSIX[^ACLPOSIX] (espace *system*) :
[^ACLPOSIX]: Les ACL POSIX sont des permissions supplémentaires qui viennent
s'ajouter aux modes standards du fichier (propriétaire, groupe, reste du
- monde). Avec les ACL POSIX, on peut doonner des droits à un ou plusieurs
+ monde). Avec les ACL POSIX, on peut donner des droits à un ou plusieurs
utilisateurs ou groupe, de manière spécifique.
```
42sh# mkdir /sys/fs/cgroup...
-42sh# echo 512M > /sys/fs/cgroup.../memory.max_usage_in_bytes
+42sh# echo 512M > /sys/fs/cgroup.../memory.limit_in_bytes
42sh# ./monitor group_name memhog 500
~~~ 13595 ~~~ Current memory usage: 75194368/550502400 (13%)
~~~ 13595 ~~~ Current memory usage: 150290432/550502400 (27%)
diff --git a/tutorial/3/chroot.md b/tutorial/3/chroot.md
index 30db29d..db792de 100644
--- a/tutorial/3/chroot.md
+++ b/tutorial/3/chroot.md
@@ -58,7 +58,7 @@ d'avoir de quoi bidouiller : un shell sera amplement suffisant pour commencer.
### `busybox`
-Queques mots, pour commencer, à propos du projet Busybox : c'est un programme
+Quelques mots, pour commencer, à propos du projet Busybox : c'est un programme
couteau-suisse qui implémente tous les binaires vitaux pour avoir un système
fonctionnel et utilisable : `ls`, `sh`, `cat`, mais aussi `init`, `mdev` (un
`udev`-like, cela permet de découvrir les périphériques attachés afin de les
@@ -171,7 +171,7 @@ chroot newroot/ bash
```bash
-tar xpf alpine-minirootfs-*.tar.xz -C newroot/
+tar xpf alpine-minirootfs-*.tar.gz -C newroot/
```
diff --git a/tutorial/3/oom.md b/tutorial/3/oom.md
index 596157a..511edfe 100644
--- a/tutorial/3/oom.md
+++ b/tutorial/3/oom.md
@@ -6,7 +6,7 @@ Gestion de la mémoire
Linux a une gestion de la mémoire bien particulière[^vm-overcommit] : en effet,
par défaut, `malloc(3)` ne retournera jamais `NULL`. En se basant sur
l'euristique qu'un bloc mémoire demandé ne sera pas utilisé directement et que
-de nombreux process ne feront pas un usage total des blocs qu'ils ont alloués,
+de nombreux processus ne feront pas un usage total des blocs qu'ils ont alloués,
le noyau permet d'allouer plus de mémoire qu'il n'y en a réellement
disponible. La mémoire est ainsi utilisée de manière plus efficace.
@@ -21,7 +21,7 @@ trouve dans l'impossibilité d'attribuer un bloc physiquement disponible, car il
n'y en a tout simplement plus (y compris via le swap).
Puisque le noyau ne peut pas honorer sa promesse et qu'il n'a plus la
-possibilité de retourner `NULL` au programme qui réclamme sa mémoire (il s'agit
+possibilité de retourner `NULL` au programme qui réclame sa mémoire (il s'agit
sans doute d'une simple assignation de variable à ce stade), il faut trouver
une solution si l'on veut pouvoir continuer l'exécution du programme.
@@ -107,7 +107,7 @@ mémoire autorisée au sein du `cgroup` ?
:::::
Eh oui, l'OOM-killer passe également lorsqu'un `cgroup` atteint la limite de
-mémoire qui lui est réservé. Dans ce cas évidemment, les processus pris en
+mémoire qui lui est réservée. Dans ce cas évidemment, les processus pris en
compte sont ceux contenus dans le `cgroup`.
diff --git a/tutorial/3/project-rendu.md b/tutorial/3/project-rendu.md
index d59d3d4..84905d8 100644
--- a/tutorial/3/project-rendu.md
+++ b/tutorial/3/project-rendu.md
@@ -5,7 +5,7 @@ Rendu
Est attendu d'ici le TP suivant :
-- le rendu des exercice de ce TP ;
+- le rendu des exercices de ce TP ;
- vos réponses à [l'évaluation du cours](https://virli.nemunai.re/quiz/14).
Pour les GISTRE (et en bonus pour les SRS), [un
diff --git a/tutorial/3/rendu.md b/tutorial/3/rendu.md
index ad17990..67e45c8 100644
--- a/tutorial/3/rendu.md
+++ b/tutorial/3/rendu.md
@@ -69,4 +69,4 @@ sur `rendu3`, ... ce qui vous permet d'avoir une arborescence
correspondant à ce qui est demandé, sans pour autant perdre votre
travail (ou le rendre plus difficile d'accès).
-::::
+:::::
diff --git a/tutorial/4/cgroupns.md b/tutorial/4/cgroupns.md
new file mode 100644
index 0000000..33567b1
--- /dev/null
+++ b/tutorial/4/cgroupns.md
@@ -0,0 +1,305 @@
+Le *namespace* `cgroup` {#cgroupns}
+-----------------------
+
+### Introduction
+
+L'espace de noms `cgroup`, introduit dans Linux 4.6, permet de virtualiser la
+vue d'un processus sur l'arborescence des *Control Groups*. Au sein d'un
+*namespace* `cgroup`, la racine vue par le processus correspond en fait à un
+sous-groupe de l'arborescence globale.
+
+
+### Pourquoi virtualiser les *cgroups* ?
+
+Sans le *namespace* `cgroup`, un processus dans un conteneur pourrait :
+
+- Voir l'arborescence complète des *cgroups* du système hôte
+- Obtenir des informations sur d'autres conteneurs
+- Comprendre la structure organisationnelle du système
+
+Le *namespace* `cgroup` permet de :
+
+- Masquer l'arborescence globale des *cgroups*
+- Faciliter la migration de conteneurs (l'arborescence reste cohérente)
+- Renforcer l'isolation entre conteneurs
+
+
+### Utilisation pratique
+
+#### Observer les *cgroups* sans isolation\
+
+Commençons par observer notre position dans l'arborescence des *cgroups* :
+
+
+```bash
+42sh$ cat /proc/self/cgroup
+0::/user.slice/user-1000.slice/session-3.scope
+```
+
+
+Cette ligne nous indique que nous nous trouvons dans le *cgroup* unifié
+`/user.slice/user-1000.slice/session-3.scope`.
+
+Nous pouvons également explorer l'arborescence complète :
+
+
+```bash
+42sh$ ls /sys/fs/cgroup/
+cgroup.controllers cpuset.cpus.effective memory.pressure
+cgroup.max.depth cpuset.mems.effective sys-fs-fuse-connections.mount
+cgroup.max.descendants dev-hugepages.mount sys-kernel-config.mount
+cgroup.procs dev-mqueue.mount sys-kernel-debug.mount
+cgroup.stat init.scope sys-kernel-tracing.mount
+cgroup.subtree_control io.pressure system.slice
+cgroup.threads memory.numa_stat user.slice
+cpu.pressure memory.stat
+```
+
+
+
+#### S'isoler dans un nouveau *namespace* `cgroup`\
+
+Créons maintenant un nouveau *namespace* `cgroup` :
+
+
+```bash
+42sh$ unshare --cgroup /bin/bash
+ incgroupns$ cat /proc/self/cgroup
+ 0::/
+```
+
+
+Notre processus se voit maintenant à la racine de l'arborescence des *cgroups* !
+En réalité, il se trouve toujours au même endroit dans l'arborescence globale,
+mais sa vue a été virtualisée.
+
+Si nous regardons le contenu de `/sys/fs/cgroup/` :
+
+
+```bash
+ incgroupns$ ls /sys/fs/cgroup/
+ cgroup.controllers cgroup.threads io.pressure
+ cgroup.events cpu.pressure memory.numa_stat
+ cgroup.freeze cpu.stat memory.pressure
+ cgroup.max.depth cpuset.cpus memory.stat
+ cgroup.max.descendants cpuset.cpus.effective
+ cgroup.procs cpuset.mems
+ cgroup.stat cpuset.mems.effective
+ cgroup.subtree_control io.stat
+```
+
+
+Nous voyons seulement notre sous-arbre, pas l'arborescence complète du système.
+
+
+#### Créer des sous-*cgroups*\
+
+Dans notre nouveau *namespace*, nous pouvons créer des sous-groupes :
+
+
+```bash
+ incgroupns$ mkdir /sys/fs/cgroup/mysubgroup
+ incgroupns$ ls /sys/fs/cgroup/
+ cgroup.controllers cgroup.threads mysubgroup
+ cgroup.events cpu.pressure ...
+ ...
+```
+
+
+Ces sous-groupes sont en réalité créés dans notre branche de l'arborescence
+globale. Depuis l'extérieur du *namespace*, ils apparaîtraient sous un chemin
+différent.
+
+
+### Exemple avec Docker
+
+Docker utilise le *namespace* `cgroup` pour isoler la vue des *cgroups* dans
+les conteneurs. Observons cela :
+
+
+```bash
+42sh$ docker run --rm -it debian /bin/bash
+ indocker# cat /proc/self/cgroup
+ 0::/
+
+ indocker# ls /sys/fs/cgroup/
+ cgroup.controllers cpu.max memory.events
+ cgroup.events cpu.pressure memory.high
+ cgroup.freeze cpu.stat memory.low
+ cgroup.kill cpu.weight memory.max
+ cgroup.max.depth io.max memory.min
+ cgroup.max.descendants io.pressure memory.numa_stat
+ cgroup.procs io.stat memory.oom.group
+ cgroup.stat io.weight memory.pressure
+ cgroup.subtree_control memory.current memory.stat
+ cgroup.threads memory.events.local memory.swap.current
+ cgroup.type ...
+```
+
+
+Le conteneur se voit à la racine, bien qu'il soit en réalité placé dans un
+sous-groupe dédié de l'arborescence globale.
+
+
+### Vérifier la position réelle dans l'arborescence
+
+Depuis l'hôte, nous pouvons voir la véritable position d'un conteneur :
+
+
+```bash
+42sh$ docker inspect mycontainer | grep -A5 CgroupParent
+ "CgroupParent": "",
+ "CgroupDriver": "systemd",
+
+42sh$ ps aux | grep containerd-shim
+root 12345 /usr/bin/containerd-shim-runc-v2 ...
+
+42sh$ cat /proc/12345/cgroup
+0::/system.slice/docker-abc123def456.scope
+```
+
+
+Le processus du conteneur se trouve dans un sous-groupe bien spécifique, mais
+grâce au *namespace* `cgroup`, il se perçoit à la racine.
+
+
+### Combinaison avec le *namespace* `mount`
+
+Pour que l'isolation soit complète, il faut généralement combiner le *namespace*
+`cgroup` avec le *namespace* `mount` afin de remonter `/sys/fs/cgroup` :
+
+
+```bash
+42sh# unshare --cgroup --mount /bin/bash
+ incgroupns# mount -t cgroup2 none /sys/fs/cgroup
+ incgroupns# ls /sys/fs/cgroup/
+ # Vue limitée à notre sous-arbre
+```
+
+
+Sans remonter le *cgroup*, nous verrions toujours l'arborescence complète via
+l'ancien point de montage.
+
+
+### Cas d'usage
+
+#### Migration de conteneurs\
+
+Lors de la migration d'un conteneur avec des outils comme CRIU (Checkpoint/Restore
+In Userspace), le *namespace* `cgroup` garantit que l'arborescence des *cgroups*
+reste cohérente du point de vue du processus, même si la structure de l'hôte
+cible est différente.
+
+
+#### Isolation de sécurité\
+
+Sans *namespace* `cgroup`, un processus malveillant dans un conteneur pourrait :
+
+- Lire `/sys/fs/cgroup/` pour découvrir d'autres conteneurs
+- Analyser les métriques d'autres processus
+- Déduire des informations sur l'architecture du système
+
+
+#### Délégation de contrôle\
+
+Le *namespace* `cgroup` permet de donner à un utilisateur non-privilégié le
+contrôle d'une sous-arborescence de *cgroups*, sans lui donner accès à
+l'arborescence globale.
+
+
+### Exemple en C
+
+Voici un exemple de création d'un *namespace* `cgroup` en C :
+
+
+```c
+#define _GNU_SOURCE
+#include
+#include
+#include
+#include
+#include
+
+static int child_func(void *arg)
+{
+ FILE *fp;
+ char line[256];
+
+ printf("=== Dans le namespace cgroup ===\n");
+
+ fp = fopen("/proc/self/cgroup", "r");
+ if (fp == NULL) {
+ perror("fopen");
+ return EXIT_FAILURE;
+ }
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ printf(" %s", line);
+ }
+
+ fclose(fp);
+
+ return 0;
+}
+
+#define STACK_SIZE (1024 * 1024)
+static char child_stack[STACK_SIZE];
+
+int main(void)
+{
+ pid_t pid;
+ FILE *fp;
+ char line[256];
+
+ printf("=== Avant le namespace cgroup ===\n");
+
+ fp = fopen("/proc/self/cgroup", "r");
+ if (fp != NULL) {
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ printf(" %s", line);
+ }
+ fclose(fp);
+ }
+
+ printf("\n");
+
+ pid = clone(child_func, child_stack + STACK_SIZE,
+ CLONE_NEWCGROUP | SIGCHLD, NULL);
+ if (pid == -1) {
+ perror("clone");
+ exit(EXIT_FAILURE);
+ }
+
+ waitpid(pid, NULL, 0);
+
+ return 0;
+}
+```
+
+
+::::: {.code}
+
+Pour compiler et exécuter :
+
+
+```bash
+42sh$ gcc -o cgroup_ns_demo cgroup_ns_demo.c
+42sh$ ./cgroup_ns_demo
+=== Avant le namespace cgroup ===
+ 0::/user.slice/user-1000.slice/session-3.scope
+
+=== Dans le namespace cgroup ===
+ 0::/
+```
+
+
+:::::
+
+
+### Aller plus loin {-}
+
+Pour plus d'informations :
+
+- `cgroup_namespaces(7)` - page de manuel
+- [Cgroup Namespace](https://lwn.net/Articles/621006/) :
+- [Control Group v2](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html) : Documentation du noyau sur cgroup v2
diff --git a/tutorial/4/filesystem.md b/tutorial/4/filesystem.md
index 18a9cd0..16936da 100644
--- a/tutorial/4/filesystem.md
+++ b/tutorial/4/filesystem.md
@@ -31,7 +31,7 @@ combinaison de chaque couche.
### Historique
-Les premières implémentations de ce type de systèmes de fichiers est apparu
+Les premières implémentations de ce type de systèmes de fichiers sont apparues
avec les LiveCD : on disposait d'une distribution Linux complètement
opérationnelle sur un support en lecture seule, mais on pouvait dédier un
espace de stockage sur son disque dur (ou en RAM, au travers d'un `tmpfs`) pour
@@ -42,7 +42,7 @@ Historiquement, le noyau Linux devait être *patché* pour supporter ce type de
système de fichiers (que ce soit `unionfs` ou `aufs`, les deux principaux
*patch* apportant cette fonctionnalité). Les systèmes BSD disposent d'une
implémentation depuis au moins 1995 et c'est SunOS qui fut le premier OS à
-développer cette technique dès 1986 (pour un système de fichier appelé
+développer cette technique dès 1986 (pour un système de fichiers appelé
*Translucent File Service*). Pour Linux, il aura fallu attendre 2014 pour voir
l'arrivée du système de fichier OverlayFS dans un noyau sans *patch*.
diff --git a/tutorial/4/howto.md b/tutorial/4/howto.md
index f4e5dbf..517581d 100644
--- a/tutorial/4/howto.md
+++ b/tutorial/4/howto.md
@@ -79,7 +79,7 @@ processus se fait en fonction des *flags* qui sont passés. On retrouve donc :
Le nom du *flag* `CLONE_NEWNS` est historique et assez peu explicite
contrairement aux autres : il désigne en fait l'espace de nom `mount`.
-Au départ, les *namespace*s ont étés pensés pour former un tout : une couche
+Au départ, les *namespace*s ont été pensés pour former un tout : une couche
d'isolation complète pour les processus. Mais lors des développements suivants,
il s'est avéré pratique de pouvoir choisir finement de quels aspects on
souhaitait se dissocier.
@@ -108,7 +108,7 @@ semblable à :
#define STACKSIZE (1024 * 1024)
static char child_stack[STACKSIZE];
-int clone_flags = CLONE_CGROUP | CLONE_NEWNET | SIGCHLD;
+int clone_flags = CLONE_NEWCGROUP | CLONE_NEWNET | SIGCHLD;
pid_t pid = clone(do_execvp, // First function executed by child
child_stack + STACKSIZE, // Assume stack grows downward
@@ -121,13 +121,41 @@ pid_t pid = clone(do_execvp, // First function executed by child
Dans cet exemple, le processus fils créé disposera d'un nouvel espace de noms
pour les *CGroups* et disposera d'une nouvelle pile réseau.
+::::: {.more}
+
+#### Compilation des exemples C {-}
+\
+
+Pour compiler les programmes C utilisant les namespaces, aucune bibliothèque
+spéciale n'est requise au-delà de la bibliothèque C standard :
+
+
+```bash
+42sh$ gcc -o mon_programme mon_programme.c
+```
+
+
+Notez que certains appels système utilisés avec les namespaces nécessitent la
+définition de `_GNU_SOURCE` au début du fichier source pour accéder aux
+extensions GNU :
+
+
+```c
+#define _GNU_SOURCE
+#include
+// ...
+```
+
+
+:::::
+
::::: {.question}
#### Quel est le rôle du *flag* `SIGCHLD` ? {-}
\
Lorsque l'on crée un nouveau processus, on ajoute l'option `SIGCHLD` afin
-d'être notifié par signal lorsque notre processus fil a terminé son
+d'être notifié par signal lorsque notre processus fils a terminé son
exécution. Cela permet d'être réveillé de notre `wait(2)`.
:::::
diff --git a/tutorial/4/intro.md b/tutorial/4/intro.md
index 4e3ce96..9e97562 100644
--- a/tutorial/4/intro.md
+++ b/tutorial/4/intro.md
@@ -89,7 +89,7 @@ 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}
+#### L'espace de noms `network` {.unnumbered}
Depuis Linux 2.6.29.
@@ -149,9 +149,9 @@ Lorsque l'on souhaite mesurer un écoulement de temps, la méthode naïve consis
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
+intervient, ... Pour pallier 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
+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.
diff --git a/tutorial/4/ipcns.md b/tutorial/4/ipcns.md
new file mode 100644
index 0000000..d5d8a62
--- /dev/null
+++ b/tutorial/4/ipcns.md
@@ -0,0 +1,514 @@
+Le *namespace* `IPC` {#ipc-ns}
+-------------------
+
+### Introduction
+
+L'espace de noms `IPC`, introduit dans Linux 2.6.19, isole les objets de
+communication inter-processus (IPC) System V et les files de messages POSIX.
+
+Les objets isolés incluent :
+
+- Les files de messages System V (`msgget`, `msgsnd`, `msgrcv`)
+- Les sémaphores System V (`semget`, `semop`)
+- Les segments de mémoire partagée System V (`shmget`, `shmat`)
+- Les files de messages POSIX (`mq_open`, `mq_send`, `mq_receive`)
+
+Une fois dans un *namespace* IPC différent, un processus ne peut communiquer
+qu'avec les processus du même *namespace* via ces mécanismes IPC.
+
+
+### Pourquoi isoler les IPC ?
+
+Sans isolation IPC, des processus dans différents conteneurs pourraient :
+
+- Communiquer entre eux via des files de messages partagées
+- Accéder à la mémoire partagée d'autres conteneurs
+- Interférer avec les sémaphores d'autres applications
+
+L'isolation IPC garantit que chaque conteneur dispose de son propre ensemble
+d'objets IPC, renforçant ainsi la sécurité et l'isolation.
+
+
+### Utilisation pratique
+
+#### Observer les objets IPC du système\
+
+La commande `ipcs` permet de lister tous les objets IPC du système :
+
+
+```bash
+42sh$ ipcs
+
+------ Message Queues --------
+key msqid owner perms used-bytes messages
+
+------ Shared Memory Segments --------
+key shmid owner perms bytes nattch status
+0x00000000 32768 alice 600 524288 2 dest
+
+------ Semaphore Arrays --------
+key semid owner perms nsems
+0x12345678 0 bob 666 1
+```
+
+
+Cette commande nous montre tous les objets IPC visibles dans notre *namespace*
+actuel.
+
+
+#### Créer une file de messages System V\
+
+Créons d'abord une file de messages dans notre *namespace* initial :
+
+
+```c
+// ipc_create.c
+#include
+#include
+#include
+#include
+
+int main(void)
+{
+ key_t key;
+ int msgid;
+
+ // Créer une clé unique
+ key = ftok("/tmp", 'A');
+ if (key == -1) {
+ perror("ftok");
+ exit(EXIT_FAILURE);
+ }
+
+ // Créer une file de messages
+ msgid = msgget(key, 0666 | IPC_CREAT);
+ if (msgid == -1) {
+ perror("msgget");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("File de messages créée avec l'ID : %d\n", msgid);
+ printf("Clé : 0x%08x\n", key);
+
+ return 0;
+}
+```
+
+
+::::: {.code}
+
+Compilation et exécution :
+
+
+```bash
+42sh$ gcc -o ipc_create ipc_create.c
+42sh$ touch /tmp/ipc_key_file
+42sh$ ./ipc_create
+File de messages créée avec l'ID : 0
+Clé : 0x41000001
+
+42sh$ ipcs -q
+------ Message Queues --------
+key msqid owner perms used-bytes messages
+0x41000001 0 alice 666 0 0
+```
+
+
+:::::
+
+
+#### S'isoler dans un nouveau *namespace* IPC\
+
+Maintenant, créons un nouveau *namespace* IPC :
+
+
+```bash
+42sh$ unshare --ipc /bin/bash
+ inipcns$ ipcs -q
+ ------ Message Queues --------
+ key msqid owner perms used-bytes messages
+```
+
+
+Notre nouveau *namespace* ne contient aucun objet IPC ! La file de messages
+créée précédemment n'est pas visible ici.
+
+Si nous créons une nouvelle file de messages dans ce *namespace* :
+
+
+```bash
+ inipcns$ ./ipc_create
+ File de messages créée avec l'ID : 0
+ Clé : 0x41000001
+
+ inipcns$ ipcs -q
+ ------ Message Queues --------
+ key msqid owner perms used-bytes messages
+ 0x41000001 0 alice 666 0 0
+```
+
+
+Cette nouvelle file a le même ID (0) et la même clé que celle créée dans le
+*namespace* initial, mais il s'agit d'un objet complètement distinct.
+
+
+#### Communication entre processus dans le même *namespace*\
+
+Créons un exemple de communication par file de messages :
+
+
+```c
+// ipc_send.c
+#include
+#include
+#include
+#include
+#include
+
+struct message {
+ long mtype;
+ char mtext[100];
+};
+
+int main(void)
+{
+ key_t key;
+ int msgid;
+ struct message msg;
+
+ key = ftok("/tmp", 'A');
+ msgid = msgget(key, 0666 | IPC_CREAT);
+
+ msg.mtype = 1;
+ snprintf(msg.mtext, sizeof(msg.mtext), "Hello from PID %d", getpid());
+
+ if (msgsnd(msgid, &msg, sizeof(msg.mtext), 0) == -1) {
+ perror("msgsnd");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Message envoyé : %s\n", msg.mtext);
+
+ return 0;
+}
+```
+
+
+
+```c
+// ipc_receive.c
+#include
+#include
+#include
+#include
+
+struct message {
+ long mtype;
+ char mtext[100];
+};
+
+int main(void)
+{
+ key_t key;
+ int msgid;
+ struct message msg;
+
+ key = ftok("/tmp", 'A');
+ msgid = msgget(key, 0666 | IPC_CREAT);
+
+ if (msgrcv(msgid, &msg, sizeof(msg.mtext), 1, 0) == -1) {
+ perror("msgrcv");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Message reçu : %s\n", msg.mtext);
+
+ return 0;
+}
+```
+
+
+::::: {.code}
+
+Compilation :
+
+
+```bash
+42sh$ gcc -o ipc_send ipc_send.c
+42sh$ gcc -o ipc_receive ipc_receive.c
+```
+
+
+Test dans le même *namespace* :
+
+
+```bash
+# Terminal 1
+42sh$ ./ipc_receive
+# Attend un message...
+
+# Terminal 2
+42sh$ ./ipc_send
+Message envoyé : Hello from PID 12345
+
+# Terminal 1 reçoit :
+Message reçu : Hello from PID 12345
+```
+
+
+:::::
+
+
+#### Isolation entre *namespaces*\
+
+Maintenant, testons avec deux *namespaces* IPC différents :
+
+
+```bash
+# Terminal 1 - namespace IPC A
+42sh$ unshare --ipc /bin/bash
+ ipcns-A$ ./ipc_receive
+ # Attend un message...
+
+# Terminal 2 - namespace IPC B (différent)
+42sh$ unshare --ipc /bin/bash
+ ipcns-B$ ./ipc_send
+ Message envoyé : Hello from PID 23456
+
+# Terminal 1 ne reçoit RIEN car les namespaces sont différents
+```
+
+
+Les deux processus utilisent la même clé IPC, mais comme ils sont dans des
+*namespaces* différents, ils ne peuvent pas communiquer.
+
+
+### Exemple avec la mémoire partagée
+
+Voici un exemple utilisant la mémoire partagée System V :
+
+
+```c
+// shm_demo.c
+#include
+#include
+#include
+#include
+#include
+#include
+
+int main(void)
+{
+ key_t key;
+ int shmid;
+ char *data;
+
+ // Créer une clé
+ key = ftok("/tmp", 'S');
+
+ // Créer un segment de mémoire partagée de 1024 octets
+ shmid = shmget(key, 1024, 0644 | IPC_CREAT);
+ if (shmid == -1) {
+ perror("shmget");
+ exit(EXIT_FAILURE);
+ }
+
+ // Attacher le segment
+ data = shmat(shmid, NULL, 0);
+ if (data == (char *)(-1)) {
+ perror("shmat");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Segment de mémoire partagée attaché\n");
+ printf("Écriture dans la mémoire partagée...\n");
+
+ sprintf(data, "Hello from PID %d in namespace", getpid());
+
+ printf("Contenu : %s\n", data);
+ printf("Appuyez sur Entrée pour détacher...\n");
+ getchar();
+
+ // Détacher
+ shmdt(data);
+
+ printf("Voulez-vous supprimer le segment ? (o/n) : ");
+ char choice = getchar();
+ if (choice == 'o' || choice == 'O') {
+ shmctl(shmid, IPC_RMID, NULL);
+ printf("Segment supprimé\n");
+ }
+
+ return 0;
+}
+```
+
+
+::::: {.code}
+
+Compilation et test :
+
+
+```bash
+42sh$ gcc -o shm_demo shm_demo.c
+
+# Dans le namespace initial
+42sh$ ./shm_demo &
+Segment de mémoire partagée attaché
+Écriture dans la mémoire partagée...
+Contenu : Hello from PID 12345 in namespace
+
+42sh$ ipcs -m
+------ Shared Memory Segments --------
+key shmid owner perms bytes nattch status
+0x53000001 0 alice 644 1024 1
+
+# Dans un nouveau namespace IPC
+42sh$ unshare --ipc /bin/bash
+ inipcns$ ipcs -m
+ ------ Shared Memory Segments --------
+ key shmid owner perms bytes nattch status
+
+ # Aucun segment visible !
+```
+
+
+:::::
+
+
+### Files de messages POSIX
+
+Le *namespace* IPC isole également les files de messages POSIX (qui sont
+différentes des files System V) :
+
+
+```c
+// mqueue_demo.c
+#include
+#include
+#include
+#include
+#include
+
+int main(void)
+{
+ mqd_t mq;
+ struct mq_attr attr;
+ char buffer[1024];
+
+ // Configurer les attributs de la file
+ attr.mq_flags = 0;
+ attr.mq_maxmsg = 10;
+ attr.mq_msgsize = 1024;
+ attr.mq_curmsgs = 0;
+
+ // Créer ou ouvrir une file de messages POSIX
+ mq = mq_open("/myqueue", O_CREAT | O_RDWR, 0644, &attr);
+ if (mq == (mqd_t)-1) {
+ perror("mq_open");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("File de messages POSIX créée : /myqueue\n");
+
+ // Envoyer un message
+ sprintf(buffer, "Hello from PID %d", getpid());
+ if (mq_send(mq, buffer, strlen(buffer) + 1, 0) == -1) {
+ perror("mq_send");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Message envoyé : %s\n", buffer);
+
+ // Recevoir le message
+ if (mq_receive(mq, buffer, 1024, NULL) == -1) {
+ perror("mq_receive");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Message reçu : %s\n", buffer);
+
+ mq_close(mq);
+ mq_unlink("/myqueue");
+
+ return 0;
+}
+```
+
+
+::::: {.code}
+
+Pour compiler (nécessite la bibliothèque `librt`) :
+
+
+```bash
+42sh$ gcc -o mqueue_demo mqueue_demo.c -lrt
+42sh$ ./mqueue_demo
+File de messages POSIX créée : /myqueue
+Message envoyé : Hello from PID 12345
+Message reçu : Hello from PID 12345
+```
+
+
+Les files de messages POSIX peuvent être listées dans `/dev/mqueue/` :
+
+
+```bash
+42sh$ ls -l /dev/mqueue/
+total 0
+-rw-r--r-- 1 alice alice 80 Nov 15 10:30 myqueue
+```
+
+
+Dans un nouveau *namespace* IPC, ce répertoire sera vide.
+
+:::::
+
+
+### Combinaison avec d'autres *namespaces*
+
+En pratique, le *namespace* IPC est souvent combiné avec d'autres *namespaces*
+pour une isolation complète :
+
+
+```bash
+42sh# unshare --ipc --pid --mount --fork --mount-proc /bin/bash
+ incontainer# # Conteneur isolé avec IPC, PID et mount namespaces
+```
+
+
+
+### Nettoyage des objets IPC
+
+Les objets IPC persistent généralement après la terminaison des processus qui
+les ont créés. Pour les nettoyer :
+
+
+```bash
+# Supprimer une file de messages
+42sh$ ipcrm -q
+
+# Supprimer un segment de mémoire partagée
+42sh$ ipcrm -m
+
+# Supprimer un sémaphore
+42sh$ ipcrm -s
+
+# Ou supprimer par clé
+42sh$ ipcrm -Q 0x41000001
+```
+
+
+Lorsqu'un *namespace* IPC est détruit (tous les processus terminés), tous ses
+objets IPC sont automatiquement nettoyés.
+
+
+### Aller plus loin {-}
+
+Pour plus d'informations :
+
+- `ipc_namespaces(7)` - page de manuel
+- `ipcs(1)` - lister les objets IPC
+- `ipcrm(1)` - supprimer les objets IPC
+- `svipc(7)` - aperçu de System V IPC
+- `mq_overview(7)` - aperçu des files de messages POSIX
diff --git a/tutorial/4/lesson.md b/tutorial/4/lesson.md
index e8d4cbc..fabd2c9 100644
--- a/tutorial/4/lesson.md
+++ b/tutorial/4/lesson.md
@@ -8,5 +8,5 @@ abstract: |
Le but de cette seconde partie sur les mécanismes internes du noyau
va nous permettre d'utiliser les commandes et les appels système
relatifs aux espaces de noms du noyau Linux ainsi que d'appréhender
- la complexité des sytèmes de fichiers.
+ la complexité des systèmes de fichiers.
...
diff --git a/tutorial/4/lsns.md b/tutorial/4/lsns.md
index ec99913..720a09f 100644
--- a/tutorial/4/lsns.md
+++ b/tutorial/4/lsns.md
@@ -40,7 +40,7 @@ Cette commande nous dévoile déjà de nombreuses choses :
contenerisé » (dans un *namespace*). Le processus initial de la machine se
retrouve donc dans des espaces de nom, tout comme les processus d'un conteneur.
-- On aperçoit un genre de hiérarchie dans certain cas.
+- On aperçoit un genre de hiérarchie dans certains cas.
- La première colonne nous renseigne sur l'identifiant du *namespace*.
diff --git a/tutorial/4/mount.md b/tutorial/4/mount.md
index b40d33d..d882f63 100644
--- a/tutorial/4/mount.md
+++ b/tutorial/4/mount.md
@@ -168,7 +168,7 @@ esclave ne propagera pas ses nouveaux points de montage à son *maître*.
```bash
# Suite de l'exemple précédent
-cd /mnt/test-slave
+mkdir /mnt/test-slave
# Duplication de l'accroche, sans s'occuper des éventuels sous-accroches
mount --bind /mnt/test-shared /mnt/test-slave
diff --git a/tutorial/4/mountns.md b/tutorial/4/mountns.md
index 4fa7f09..acf7816 100644
--- a/tutorial/4/mountns.md
+++ b/tutorial/4/mountns.md
@@ -189,7 +189,7 @@ On considère préalablement que l'environnement est propice à la réalisation
```
42sh# mkdir -p /mnt/newroot
42sh# mount -t tmpfs none /mnt/newroot
-42sh# wget https://dl-cdn.alpinelinux.org/alpine/v3.14/releases/x86_64/alpine-minirootfs-3.14.8-x86_64.tar.gz
+42sh# wget https://dl-cdn.alpinelinux.org/alpine/v3.20/releases/x86_64/alpine-minirootfs-3.20.3-x86_64.tar.gz
42sh# tar xpf alpine-minirootfs-*.tar.gz -C /mnt/newroot
42sh# cd /
```
diff --git a/tutorial/4/namespaces-recap.md b/tutorial/4/namespaces-recap.md
new file mode 100644
index 0000000..6267dbb
--- /dev/null
+++ b/tutorial/4/namespaces-recap.md
@@ -0,0 +1,532 @@
+\newpage
+
+Récapitulatif des *namespaces*
+===============================
+
+Nous venons d'explorer en détail les huit types d'espaces de noms disponibles
+dans le noyau Linux. Avant de conclure cette partie, récapitulons les concepts
+clés et les meilleures pratiques pour utiliser efficacement ces mécanismes
+d'isolation.
+
+
+## Tableau comparatif des *namespaces*
+
+Le tableau suivant résume les caractéristiques principales de chaque type
+d'espace de noms :
+
+| *Namespace* | Flag `clone()` | Depuis | Isole | Privilèges requis* |
+|-------------|----------------|--------|-------|-------------------|
+| **mount** | `CLONE_NEWNS` | 2.4.19 | Points de montage | Oui |
+| **UTS** | `CLONE_NEWUTS` | 2.6.19 | Hostname, domaine NIS | Oui |
+| **IPC** | `CLONE_NEWIPC` | 2.6.19 | Objets IPC System V et POSIX | Oui |
+| **PID** | `CLONE_NEWPID` | 2.6.24 | Arbre de processus | Oui |
+| **network** | `CLONE_NEWNET` | 2.6.29 | Interfaces, routes, ports | Oui |
+| **user** | `CLONE_NEWUSER` | 3.8 | UIDs, GIDs, capabilities | **Non** |
+| **cgroup** | `CLONE_NEWCGROUP` | 4.6 | Vue arborescence cgroup | Oui |
+| **time** | `CLONE_NEWTIME` | 5.6 | Horloges monotones | Oui |
+
+*\* Sauf si combiné avec un *namespace* `user`*
+
+
+## Ce que chaque *namespace* vous permet de faire
+
+### `mount` -- Systèmes de fichiers isolés
+
+**Fonctionnalité :** Isole l'arborescence des points de montage.
+
+**Permet de :**
+- Créer un système de fichiers racine différent (`pivot_root`, `switch_root`)
+- Monter/démonter des partitions sans affecter l'hôte
+- Implémenter un `chroot` sécurisé (impossible de s'échapper)
+- Utiliser des systèmes de fichiers en couches (OverlayFS)
+
+**Cas d'usage typiques :**
+- Conteneurs avec leur propre filesystem
+- Environnements de build isolés
+- Systèmes d'installation et de récupération
+
+
+### `UTS` -- Identité système
+
+**Fonctionnalité :** Isole le nom d'hôte et le domaine NIS.
+
+**Permet de :**
+- Donner un nom unique à chaque conteneur
+- Éviter les conflits de nommage
+- Faciliter l'identification des conteneurs
+
+**Cas d'usage typiques :**
+- Conteneurs avec des noms de machine distincts
+- Environnements multi-tenants
+- Tests de configurations réseau
+
+
+### `IPC` -- Communication inter-processus
+
+**Fonctionnalité :** Isole les objets IPC (files de messages, sémaphores,
+mémoire partagée).
+
+**Permet de :**
+- Empêcher la communication IPC entre conteneurs
+- Isoler les applications utilisant IPC System V ou POSIX
+- Protéger contre les fuites d'informations via IPC
+
+**Cas d'usage typiques :**
+- Isolation de sécurité entre conteneurs
+- Applications legacy utilisant IPC System V
+- Environnements de test pour applications IPC
+
+
+### `PID` -- Arbre de processus virtualisé
+
+**Fonctionnalité :** Isole l'arbre des processus avec renumérotation.
+
+**Permet de :**
+- Avoir un processus `init` (PID 1) par conteneur
+- Masquer les processus de l'hôte et des autres conteneurs
+- Gérer le cycle de vie des processus indépendamment
+- Récolter les processus orphelins proprement
+
+**Cas d'usage typiques :**
+- Conteneurs avec gestion complète du cycle de vie
+- Isolation de sécurité (masquage des processus)
+- Environnements avec plusieurs niveaux d'`init`
+
+**Particularité :** Le processus doit forker après `unshare(CLONE_NEWPID)`
+pour que l'isolation soit effective.
+
+
+### `network` -- Pile réseau dédiée
+
+**Fonctionnalité :** Isole les interfaces réseau, routes, règles de pare-feu et
+ports.
+
+**Permet de :**
+- Donner une pile réseau complète à chaque conteneur
+- Réutiliser les mêmes ports dans différents conteneurs
+- Configurer des routes et pare-feu indépendants
+- Créer des topologies réseau complexes (bridges, VLAN, MACVLAN)
+
+**Cas d'usage typiques :**
+- Conteneurs avec leur propre IP
+- Tests réseau isolés
+- Micro-services avec ports identiques
+- Simulations de topologies réseau
+
+**Note :** Nécessite généralement des interfaces virtuelles (`veth`, `macvlan`,
+etc.) pour connecter les conteneurs.
+
+
+### `user` -- Privilèges virtualisés
+
+**Fonctionnalité :** Isole les UIDs, GIDs et les capabilities.
+
+**Permet de :**
+- Être root dans le conteneur sans être root sur l'hôte
+- Lancer des conteneurs sans privilèges (rootless containers)
+- Mapper des plages d'UIDs entre conteneur et hôte
+- Déléguer des capacités limitées
+
+**Cas d'usage typiques :**
+- Conteneurs rootless (podman, systemd-nspawn)
+- Environnements multi-utilisateurs sécurisés
+- Délégation contrôlée de privilèges
+
+**Particularité :** Seul *namespace* créable sans privilèges. Permet ensuite de
+créer tous les autres types de *namespaces*.
+
+**Attention :** Historiquement source de vulnérabilités ; à utiliser avec
+précaution.
+
+
+### `cgroup` -- Vue filtrée des control groups
+
+**Fonctionnalité :** Virtualise la vue de l'arborescence des cgroups.
+
+**Permet de :**
+- Masquer l'organisation des cgroups de l'hôte
+- Faciliter la migration de conteneurs
+- Empêcher la fuite d'informations système via `/sys/fs/cgroup`
+- Déléguer la gestion de sous-arbres de cgroups
+
+**Cas d'usage typiques :**
+- Renforcement de l'isolation de sécurité
+- Migration de conteneurs (CRIU)
+- Systèmes multi-tenants
+
+**Note :** Souvent combiné avec un *namespace* `mount` pour remonter
+`/sys/fs/cgroup`.
+
+
+### `time` -- Horloges virtualisées
+
+**Fonctionnalité :** Virtualise `CLOCK_MONOTONIC` et `CLOCK_BOOTTIME`.
+
+**Permet de :**
+- Décaler les horloges monotones pour un conteneur
+- Préserver l'état temporel lors de migrations
+- Accélérer le temps pour les tests
+
+**Cas d'usage typiques :**
+- Migration de conteneurs avec CRIU
+- Tests d'applications sensibles au temps
+- Simulations temporelles
+
+**Limitation :** Ne virtualise **pas** l'heure système (CLOCK_REALTIME).
+
+**Particularité :** Les offsets doivent être configurés avant de créer le
+premier processus enfant.
+
+
+## Combinaisons recommandées
+
+Les *namespaces* sont rarement utilisés seuls. Voici les combinaisons courantes
+selon les besoins d'isolation :
+
+
+### Isolation minimale (développement)
+
+Pour un environnement de développement simple avec un filesystem isolé :
+
+
+```bash
+unshare --mount --pid --fork --mount-proc /bin/bash
+```
+
+
+**Isolation :** Filesystem et processus
+**Avantages :** Rapide, simple, suffisant pour tester des installations
+**Limitations :** Partage le réseau, les utilisateurs, IPC avec l'hôte
+
+
+### Conteneur standard (production light)
+
+Pour une isolation raisonnable sans réseau séparé :
+
+
+```bash
+unshare --mount --uts --ipc --pid --fork --mount-proc /bin/bash
+```
+
+
+**Isolation :** Filesystem, processus, IPC, hostname
+**Avantages :** Bonne isolation, partage le réseau de l'hôte
+**Cas d'usage :** Services système, environnements de build
+
+
+### Conteneur avec réseau isolé
+
+Pour une isolation complète incluant le réseau :
+
+
+```bash
+unshare --mount --uts --ipc --net --pid --fork --mount-proc /bin/bash
+```
+
+
+**Isolation :** Filesystem, processus, IPC, hostname, réseau
+**Avantages :** Isolation réseau complète
+**Note :** Nécessite configuration réseau supplémentaire (veth, bridge, etc.)
+
+
+### Conteneur rootless (sans privilèges)
+
+Pour lancer un conteneur en tant qu'utilisateur normal :
+
+
+```bash
+unshare --user --map-root-user \
+ --mount --uts --ipc --net --pid \
+ --fork --mount-proc /bin/bash
+```
+
+
+**Isolation :** Complète + virtualisation des privilèges
+**Avantages :** Aucun privilège requis, sécurité renforcée
+**Cas d'usage :** Environnements multi-utilisateurs, CI/CD non-privilégiée
+
+
+### Conteneur type Docker (isolation maximale)
+
+Pour une isolation complète similaire à Docker :
+
+
+```bash
+unshare --user --map-root-user \
+ --mount --uts --ipc --net --pid --cgroup \
+ --fork --mount-proc /bin/bash
+```
+
+
+**Isolation :** Tous les namespaces (sauf `time`)
+**Avantages :** Isolation maximale
+**Note :** Équivalent approximatif de `docker run --rm -it`
+
+
+## Ordre de création des *namespaces*
+
+L'ordre dans lequel les *namespaces* sont créés peut être important :
+
+1. **`user` en premier** : Si vous voulez créer des *namespaces* sans
+ privilèges, commencez toujours par le *namespace* `user`.
+
+2. **`mount` avant `pid`** : Pour pouvoir remonter `/proc` correctement avec
+ l'option `--mount-proc`.
+
+3. **`pid` avec `--fork`** : N'oubliez jamais l'option `--fork` avec le
+ *namespace* `pid`, sinon le processus actuel ne sera pas réellement isolé.
+
+4. **`time` et `cgroup` avant le fork** : Ces deux namespaces nécessitent des
+ configurations avant la création du premier processus enfant.
+
+
+## Commandes essentielles
+
+Voici un récapitulatif des commandes les plus utiles pour travailler avec les
+*namespaces* :
+
+### Création et entrée dans des *namespaces*
+
+
+```bash
+# Créer de nouveaux namespaces et exécuter une commande
+unshare [options] [commande]
+
+# Principales options :
+# -m, --mount Namespace mount
+# -u, --uts Namespace UTS
+# -i, --ipc Namespace IPC
+# -n, --net Namespace network
+# -p, --pid Namespace PID
+# -U, --user Namespace user
+# -C, --cgroup Namespace cgroup
+# -T, --time Namespace time
+# -f, --fork Fork avant d'exécuter la commande (requis avec --pid)
+# --mount-proc Monter /proc après création du namespace
+
+# Entrer dans les namespaces d'un processus existant
+nsenter [options] [commande]
+nsenter --target
--all [commande]
+```
+
+
+### Inspection des *namespaces*
+
+
+```bash
+# Lister tous les namespaces du système
+lsns
+
+# Lister les namespaces d'un processus spécifique
+lsns -p
+
+# Voir les namespaces d'un processus
+ls -l /proc//ns/
+
+# Comparer les namespaces de deux processus
+readlink /proc//ns/net
+readlink /proc//ns/net
+```
+
+
+### Gestion réseau (namespace network)
+
+
+```bash
+# Créer un namespace network nommé
+ip netns add
+
+# Lister les namespaces network
+ip netns list
+
+# Exécuter une commande dans un namespace network
+ip netns exec
+
+# Créer une paire veth
+ip link add veth0 type veth peer name veth1
+
+# Déplacer une interface dans un namespace
+ip link set veth1 netns
+```
+
+
+
+## Appels système
+
+Pour les développeurs, voici les appels système principaux :
+
+
+```c
+// Créer un nouveau processus dans de nouveaux namespaces
+pid_t clone(int (*fn)(void *), void *stack, int flags, void *arg);
+// flags: CLONE_NEWNS, CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWPID,
+// CLONE_NEWNET, CLONE_NEWUSER, CLONE_NEWCGROUP, CLONE_NEWTIME
+
+// Se dissocier de namespaces actuels
+int unshare(int flags);
+
+// Rejoindre les namespaces d'un autre processus
+int setns(int fd, int nstype);
+// fd: file descriptor de /proc/
/ns/
+// nstype: 0 ou CLONE_NEW* pour vérification de type
+
+// Obtenir un file descriptor vers un processus (pour setns)
+int pidfd_open(pid_t pid, unsigned int flags);
+```
+
+
+
+## Bonnes pratiques
+
+### Sécurité
+
+1. **Privilèges minimaux** : Utilisez le *namespace* `user` quand possible pour
+ éviter d'exécuter des conteneurs en tant que root.
+
+2. **Combinaison d'isolations** : Un seul namespace ne suffit généralement pas
+ pour une isolation sécurisée. Combinez plusieurs namespaces.
+
+3. **User namespace avec précaution** : Bien que pratique, le *namespace*
+ `user` a été source de nombreuses vulnérabilités. Assurez-vous d'utiliser un
+ noyau récent et correctement patché.
+
+4. **Nettoyage des ressources** : Les namespaces persistent tant qu'ils sont
+ référencés. Utilisez `umount` pour les bind mounts qui maintiennent des
+ namespaces actifs.
+
+5. **Capabilities** : Même dans un *namespace* `user`, les capabilities sont
+ limitées à l'intérieur du namespace. Ne comptez pas sur elles pour des
+ actions hors namespace.
+
+
+### Performance
+
+1. **Coût minimal** : La création de namespaces a un coût négligeable en termes
+ de performance. N'hésitez pas à les utiliser.
+
+2. **Réseau** : Le type d'interface virtuelle utilisé (`veth`, `macvlan`,
+ `ipvlan`) peut avoir un impact significatif sur les performances réseau.
+
+3. **OverlayFS vs device-mapper** : Pour le stockage, OverlayFS est
+ généralement plus performant que les snapshots LVM (device-mapper).
+
+
+### Débogage
+
+1. **`lsns` est votre ami** : Utilisez `lsns` pour comprendre rapidement
+ l'organisation des namespaces sur votre système.
+
+2. **Inspecter /proc** : Les fichiers dans `/proc/
/ns/` sont essentiels
+ pour comprendre dans quels namespaces se trouve un processus.
+
+3. **Bind mounts pour persistence** : Utilisez `mount --bind` sur les fichiers
+ de `/proc//ns/` pour maintenir un namespace actif même après la
+ terminaison du processus.
+
+4. **Logs et `strace`** : En cas de problème, `strace` peut vous montrer
+ exactement quels appels système échouent et pourquoi.
+
+
+## Limitations et pièges courants
+
+### Namespace `PID`
+
+- **Oubli du `--fork`** : Sans fork, le processus actuel reste dans l'ancien
+ namespace PID.
+- **Bash et PID 1** : Bash peut avoir des comportements inattendus en tant que
+ PID 1 (voir pidns.md pour les détails).
+- **`/proc` doit être remonté** : Sinon `ps`, `top` montrent tous les processus
+ du système.
+
+
+### Namespace `mount`
+
+- **Propagation des montages** : Attention aux politiques `shared`, `slave`,
+ `private`. Par défaut, utilisez `mount --make-rslave /` pour éviter les
+ fuites.
+- **`pivot_root` vs `chroot`** : `pivot_root` est plus sûr mais plus complexe à
+ mettre en œuvre.
+
+
+### Namespace `network`
+
+- **Pas d'interface par défaut** : Un nouveau namespace network ne contient
+ qu'une interface loopback désactivée. Il faut configurer le réseau
+ manuellement.
+- **Complexité de la configuration** : Bridges, veth, routes, NAT... la
+ configuration réseau peut devenir complexe rapidement.
+
+
+### Namespace `user`
+
+- **MappingUID/GID limité** : Sans privilèges, vous ne pouvez mapper qu'un
+ seul UID (le vôtre vers root).
+- **Fichiers setuid** : Ne fonctionnent pas correctement dans un namespace
+ user.
+- **Restrictions par distribution** : Certaines distributions désactivent le
+ namespace user par défaut (voir setup.md).
+
+
+### Namespace `time`
+
+- **Configuration unique** : Les offsets ne peuvent être configurés qu'une fois,
+ avant le premier fork.
+- **Pas d'heure réelle** : Ne virtualise pas `CLOCK_REALTIME`, seulement les
+ horloges monotones.
+
+
+## Pour aller plus loin
+
+### Documentation officielle
+
+- Pages de manuel : `namespaces(7)`, `pid_namespaces(7)`, `user_namespaces(7)`,
+ `mount_namespaces(7)`, `network_namespaces(7)`, `ipc_namespaces(7)`,
+ `uts_namespaces(7)`, `cgroup_namespaces(7)`, `time_namespaces(7)`
+
+- Documentation du noyau :
+
+
+
+### Articles de référence
+
+- [Namespaces in operation (série LWN)](https://lwn.net/Articles/531114/) :
+ série d'articles exhaustive par Michael Kerrisk
+
+
+- [Anatomy of a user namespaces vulnerability](https://lwn.net/Articles/543273/) :
+ pour comprendre les enjeux de sécurité
+
+
+
+### Projets utilisant les namespaces
+
+- **Docker/Podman/containerd** : Containerisation d'applications
+- **systemd-nspawn** : Conteneurs légers pour systemd
+- **LXC/LXD** : Conteneurs système complets
+- **Flatpak/Snap** : Sandboxing d'applications
+- **Chrome/Firefox** : Sandboxing de processus de rendu
+- **bubblewrap** : Outil de sandboxing générique
+
+
+## Conclusion
+
+Les *namespaces* Linux constituent une brique fondamentale de la virtualisation
+légère moderne. Leur conception modulaire permet de créer des niveaux
+d'isolation sur mesure, depuis un simple environnement de développement isolé
+jusqu'à des conteneurs de production complets.
+
+La maîtrise des *namespaces* nécessite de comprendre :
+
+1. **Ce que chaque type isole** et dans quel contexte l'utiliser
+2. **Comment les combiner** pour atteindre le niveau d'isolation souhaité
+3. **Leurs interactions** et dépendances mutuelles
+4. **Leurs limitations** et les cas particuliers à gérer
+
+Combinés avec les *cgroups* (pour la limitation de ressources) et les *security
+modules* (AppArmor, SELinux pour les politiques de sécurité), les *namespaces*
+permettent de construire des environnements d'exécution sûrs, isolés et
+performants.
+
+Que vous développiez des outils de containerisation, construisiez des
+plateformes cloud, ou cherchiez simplement à mieux isoler vos applications, les
+*namespaces* sont un outil incontournable de l'écosystème Linux moderne.
diff --git a/tutorial/4/networkns.md b/tutorial/4/networkns.md
index 8fe702d..8adcd84 100644
--- a/tutorial/4/networkns.md
+++ b/tutorial/4/networkns.md
@@ -30,7 +30,7 @@ l'autre.
:::::
Afin d'amener du réseau à notre nouvel espace de nom, il va falloir lui
-attribuer des interface. En fait, nous allons pouvoir déplacer nos interfaces
+attribuer des interfaces. En fait, nous allons pouvoir déplacer nos interfaces
réseaux, dans le *namespace* vers lequel elle doit être accessible. Une
interface donnée ne peut se trouver que dans un seul *namespace* à la fois.
@@ -82,13 +82,13 @@ virli
42sh# ip netns
foo virli
42sh# ip netns exec foo ip link
-1: lo: mut 65536 qdisc noop state DOWN mode DEFAULT group default
+1: lo: mtu 65536 qdisc noop state DOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
```
Les fichiers utilisés par `ip netns` ne sont donc rien de plus que des
-*bind-mount*. Ce qui explique qu'ils soient persistant même sans processus
+*bind-mount*. Ce qui explique qu'ils soient persistants même sans processus
s'exécutant à l'intérieur.
:::::
@@ -99,7 +99,7 @@ des interfaces :
```
42sh# ip netns exec virli ip link
-1: lo: mut 65536 qdisc noop state DOWN mode DEFAULT group default
+1: lo: mtu 65536 qdisc noop state DOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
```
@@ -175,11 +175,13 @@ struct nlmsghdr {
```
-Parmi les fonctionnalités de Netlink, nous allons utiliser le module NIS
-(Network Interface Service)[^RFC3549NIS]. Il spécifie le format par lequel
+Parmi les fonctionnalités de Netlink, nous allons utiliser RTNetlink
+(Routing Netlink)[^RFC3549RTNETLINK]. Il spécifie le format par lequel
doivent commencer les données liées à l'administration d'interfaces réseau.
+Le module RTNetlink utilise la famille `NETLINK_ROUTE` pour communiquer avec
+le noyau concernant les interfaces, routes et règles de routage.
-[^RFC3549NIS]: Network Interface Service Module