Tuto 4 ready

This commit is contained in:
nemunaire 2021-10-31 20:51:17 +01:00
parent fb994050db
commit c960136430
18 changed files with 536 additions and 340 deletions

Binary file not shown.

View File

@ -1,6 +1,6 @@
include ../pandoc-opts.mk
SOURCES_TUTO = tutorial.md setup.md mount.md namespaces.md cmpns.md docker-exec.md networkns.md pidns.md mountns.md userns.md rendu.md
SOURCES_TUTO = tutorial.md mount.md intro.md setup.md howto.md setns.md setns-samples.md cmpns.md lifetime.md namespaces_more.md networkns.md pidns.md mountns.md userns.md docker-exec.md rendu.md
all: tutorial.pdf

View File

@ -1,4 +1,6 @@
## Exercice : comparaison de *namespace*
\newpage
### Exercice : comparaison de *namespace* -- `cmpns.sh`
Les *namespaces* d'un programme sont exposés sous forme de liens symboliques
dans le répertoire `/proc/<PID>/ns/`.
@ -7,10 +9,12 @@ Deux programmes qui partagent un même *namespace* auront un lien vers la même
structure de données.
Écrivons un script ou un programme, `cmpns`, permettant de déterminer si deux
programmes s'exécutent dans les mêmes *namespaces*.
programmes s'exécutent dans les mêmes *namespaces*. On ignorera les
*namespace*s `*_for_children`, car ils ne font pas partie du cycle d'exécution
que l'on cherche à comparer.
### Exemples {.unnumbered}
#### Exemples {.unnumbered}
<div lang="en-US">
```
@ -20,6 +24,7 @@ programmes s'exécutent dans les mêmes *namespaces*.
- mnt: differ
- net: differ
- pid: differ
- time: same
- user: same
- uts: same
```
@ -33,6 +38,7 @@ programmes s'exécutent dans les mêmes *namespaces*.
- mnt: same
- net: same
- pid: same
- time: same
- user: same
- uts: same
```
@ -52,6 +58,7 @@ Et pourquoi pas :
- mnt: differ
- net: same
- pid: same
- time: same
- user: same
- uts: same
```

View File

@ -1,3 +1,5 @@
\newpage
Exercice : `docker exec`
------------------------

View File

@ -1,142 +1,28 @@
\newpage
Les espaces de noms -- *namespaces* {#namespaces}
===================================
Utiliser les *namespace*s
-------------------------
## Introduction
### S'isoler dans un nouveau *namespace*
Les espaces de noms du noyau, les *namespaces*, permettent de
dupliquer certaines structures, habituellement considérées uniques
pour le noyau, dans le but de les isoler d'un groupe de processus à un
autre.
Si l'on voit l'isolation procurée par les *namespace*s en parallèle avec les
machines virtuelle, on peut se dire qu'il suffit d'exécuter un appel système
pour arriver dans un conteneur bien isolé. Cependant, le choix fait par les
développeurs de Linux a été de laisser le choix des espaces de noms dont on veut
se dissocier.
On en dénombre sept (le dernier ayant été ajouté dans Linux 4.6) : `cgroup`,
`IPC`, `network`, `mount`, `PID`, `user` et `UTS`.
L'intérêt principal de cette approche, exploitée bien après la mise en avant du
concept, est que l'utilisation des *namespace*s ne se limite pas seulement à
des machines virtuelles légères. On retrouve ainsi dans Google Chrome de
nombreuses utilisations des *namespace*s dans le simple but d'accroître la
sécurité de leur navigateur. Ainsi, les threads de rendu n'ont pas accès au
réseau et sont cloisonnés de manière transparente pour l'utilisateur.
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 pas encore *containerisables* :
[le document fondateur](https://www.kernel.org/doc/ols/2006/ols2006v1-pages-101-112.pdf)
parle ainsi d'isoler les périphériques, ou encore l'horloge. Pour ce
dernier,
[un patch a même déjà été proposé](https://lwn.net/Articles/766089/).
### L'espace de noms `mount` {#mount-ns}
Depuis Linux 2.4.19.
Cet espace de noms isole la liste des points de montage.
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.
Attention il convient cependant de prendre garde aux types de liaison existant
entre vos points de montage (voir la partie sur
[les particularités des points de montage](#mount)), car les montages et
démontages pourraient alors être répercutés dans l'espace de noms parent.
Une manière rapide pour s'assurer que nos modifications ne sortiront pas de
notre *namespace* est d'appliquer le type esclave à l'ensemble de nos points de
montage, récursivement, dès que l'on est entré dans notre nouvel espace de
noms.
<div lang="en-US">
```bash
mount --make-rslave /
```
</div>
Nous allons voir dans cette partie plusieurs méthodes pour utiliser ces espaces
de noms.
### L'espace de noms `UTS` {#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` {#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`
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
de PID : les processus de tous les PID *namespaces* apparaissent donc dans
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
les mêmes propriétés que le processus `init` usuel\ ; entre autre, si un
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`
Depuis Linux 2.6.29.
Cet espace de noms fournit une isolation pour toutes les ressources associées
aux réseaux : les interfaces, les piles protocolaires IPv4 et IPv6, les tables
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`
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` {#cgroup-ns}
Depuis Linux 4.6.
Cet espace de noms filtre l'arborescence des *Control Group* en changeant la
racine de l'arborescence des cgroups. Au sein d'un *namespace*, 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
processus (d'un système à un autre) : l'arborescence des cgroups n'a alors
plus d'importance car le processus ne voit que son groupe.
## S'isoler dans un nouveau *namespace*
### Avec son coquillage
#### Avec son coquillage\
De la même manière que l'on peut utiliser l'appel système `chroot(2)` depuis un
shell via la commande `chroot(1)`, la commande `unshare(1)` permet de faire le
@ -169,13 +55,16 @@ Nous avons pu ici modifier le nom de la machine, sans que cela n'affecte notre
machine hôte.
### Les appels systèmes
#### Les appels systèmes\
L'appel système par excellence pour contrôler l'isolation d'un nouveau
processus est `clone(2)`.
L'isolement ou non du processus est faite en fonction des `flags` qui sont
passés à la fonction :
Ce *syscall*, propre à Linux, crée habituellement un nouveau processus (mais
aussi des threads) enfant de notre processus courant, comme `fork(2)` (qui lui
est un appel système POSIX) mais prend en plus de nombreux
paramètres. L'isolement ou non du processus se fait en fonction des *flags* qui
sont passés :
* `CLONE_NEWNS`,
* `CLONE_NEWUTS`,
@ -183,16 +72,18 @@ passés à la fonction :
* `CLONE_NEWPID`,
* `CLONE_NEWNET`,
* `CLONE_NEWUSER`,
* `CLONE_NEWCGROUP`.
* `CLONE_NEWCGROUP`,
* `CLONE_NEWTIME`.
On peut bien entendu cumuler un ou plusieurs de ces `flags`, et les combiner
avec d'autres `flags` attendu par la fonction.
On peut bien entendu cumuler un ou plusieurs de ces *flags*, et les combiner
avec d'autres attendus par `clone(2)`.
Les mêmes `flags` sont utilisés lors des appels à `unshare(2)` ou `setns(2)`.
Ces mêmes *flags* sont utilisés lors des appels à `unshare(2)` ou `setns(2)`,
que nous verrons plus tard.
Pour créer un nouveau processus qui sera à la fois dans un nouvel espace de
noms réseau et dans un nouveau *namespace* `cgroup`, on écrirait un code
similaire à :
noms réseau et dans un nouveau *namespace* `cgroup`, on écrirait un code C
semblable à :
<div lang="en-US">
```c
@ -217,102 +108,30 @@ Un exemple complet d'utilisation de `clone(2)` et du *namespace* `UTS` est
donné dans le `man` de l'appel système.
## Rejoindre un *namespace*
##### `unshare`\
Rejoindre un espace de noms se fait en utilisant l'appel système `setns(2)`,
auquel on passe le *file descriptor* d'un des liens du dossier
`/proc/<PID>/ns/` :
L'appel système `clone(2)` va créer un nouveau processus, ou un nouveau
thread. Parfois, on souhaite faire entrer notre processus ou thread en cours
dans un nouvel espace de noms. Dans ce cas, on utilisera l'appel système
`unshare(2)`. Celui-ci prend uniquement en argument une liste de *flags* des
*namespace*s dont on souhaite se dissocier.
<div lang="en-US">
```c
#define _GNU_SOURCE
#include <fcntl.h>
#include <sched.h>
#include <stdlib.h>
::::: {.warning}
Le comportement de `unshare(2)` (ou `unshare(3)`) avec les *namespace*s *PID*
et *Time* n'est pas celui que l'on peut attendre !
// ./a.out /proc/PID/ns/FILE cmd args...
En effet, après avoir appelé `unshare`, le processus reste tout de même dans
son *namespace* *Time* ou *PID* d'origine, seuls ses enfants (après un appel à
`fork(2)` ou `clone(2)` par exemple) seront dans le nouveau *namespace*.
int
main(int argc, char *argv[])
{
int fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
perror("open");
return EXIT_FAILURE;
}
Cela poserait trop de problème de faire changer le PID d'un processus en cours
d'exécution, de même qu'il serait impensable que la `CLOCK_MONOTONIC` puisse
faire un saut en avant ou en arrière. Alors le choix qui a été fait est que
seuls les fils créés après l'appel à `unshare(2)` seront concrètement dans le
nouveau *namespace*. C'est dans cette situation que `pid` et `pid_for_children`
peuvent être différents dans le dossier `/proc/<PID>/ns`.
if (setns(fd, 0) == -1)
{
perror("setns");
return EXIT_FAILURE;
}
execvp(argv[2], &argv[2]);
perror("execve");
return EXIT_FAILURE;
}
```
</div>
Dans un shell, on utilisera la commande `nsenter(1)` :
<div lang="en-US">
```bash
42sh# nsenter --uts=/proc/42/ns/uts /bin/bash
```
</div>
## Durée de vie d'un *namespace* {#ns-lifetime}
Le noyau tient à jour un compteur de références pour chaque *namespace*. Dès
qu'une référence tombe à 0, l'espace de noms est automatiquement libéré, les
points de montage sont démontés, les interfaces réseaux sont réattribués à
l'espace de noms initial, ...
Ce compteur évolue selon plusieurs critères, et principalement selon le nombre
de processus qui l'utilise. C'est-à-dire que, la plupart du temps, le
*namespace* est libéré lorsque le dernier processus s'exécutant dedans se
termine.
Lorsque l'on a besoin de référencer un *namespace* (par exemple pour le faire
persister après le dernier processus), on peut utiliser un `mount bind` :
<div lang="en-US">
```bash
42sh# touch /tmp/ns/myrefns
42sh# mount --bind /proc/<PID>/ns/mount /tmp/ns/myrefns
```
</div>
De cette manière, même si le lien initial n'existe plus (si le `<PID>` s'est
terminé), `/tmp/ns/myrefns` pointera toujours au bon endroit.
On peut très bien utiliser directement ce fichier pour obtenir un descripteur
de fichier valide vers le *namespace* (pour passer à `setns(2)`).
### Faire persister un *namespace*
Il n'est pas possible de faire persister un espace de noms d'un reboot à
l'autre.
Même en étant attaché à un fichier du disque, il s'agit d'un pointeur vers une
structure du noyau, qui ne persistera pas au redémarrage.
## Aller plus loin {-}
Je vous recommande la lecture des *man* suivants :
* `namespaces(7)` : introduisant et énumérant les *namespaces* ;
Pour tout connaître en détails, [la série d'articles de Michael Kerrisk sur
les *namespaces*](https://lwn.net/Articles/531114/) est excellente ! Auquel il
faut ajouter [le petit dernier sur le `cgroup`
*namespace*](https://lwn.net/Articles/621006/).
[Cet article de Michael Crosby montrant l'utilisation de clone(2)](https://web.archive.org/web/20190206073558/http://crosbymichael.com/creating-containers-part-1.html)
est également des plus intéressants, pour ce qui concerne la programmation
plus bas-niveau.
On ne remarque pas cette bizarrerie avec `clone(2)`, car il crée déjà un
nouveau processus, son PID et sa `CLOCK_MONOTONIC` sont directement à la bonne
valeur dès l'exécution de la fonction `fn`.
:::::

159
tutorial/4/intro.md Normal file
View File

@ -0,0 +1,159 @@
\newpage
Les espaces de noms -- *namespaces* {#namespaces}
===================================
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
puissent pas interagir avec les autres processus, avoir sa propre pile
réseau, ... Voyons maintenant les *namespaces* qui vont nous permettre de faire
cela.
Initiation rapide
-----------------
Les espaces de noms du noyau, que l'on appelle *namespaces*, permettent de
dupliquer certaines structures, habituellement considérées uniques pour le
noyau, dans le but de les isoler d'un groupe de processus à un autre.
On en dénombre huit (le dernier ayant été ajouté dans Linux 5.6) : `cgroup`,
`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
pas encore *containerisables* : le document fondateur[^NSDOC] parle ainsi
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>
#### L'espace de noms `mount` {.unnumbered #mount-ns}
Depuis Linux 2.4.19.
Cet espace de noms isole la liste des points de montage.
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.
#### 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
de PID : les processus de tous les PID *namespaces* apparaissent donc dans
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
les mêmes propriétés que le processus `init` usuel\ ; entre autres, si un
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
aux réseaux : les interfaces, les piles protocolaires IPv4 et IPv6, les tables
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
processus (d'un système à un autre) : l'arborescence des *cgroups* n'a alors
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
gérés par la `libc`). Les horloges virtualisations avec ce *namespace* sont les
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.

40
tutorial/4/lifetime.md Normal file
View File

@ -0,0 +1,40 @@
### Durée de vie d'un *namespace* {#ns-lifetime}
Le noyau tient à jour un compteur de références pour chaque *namespace*. Dès
qu'une référence tombe à 0, la structure de l'espace de noms est
automatiquement libérée, les points de montage sont démontés, les interfaces
réseaux sont réattribués à l'espace de noms initial, ...
Ce compteur évolue selon plusieurs critères, et principalement selon le nombre
de processus qui l'utilisent. C'est-à-dire que, la plupart du temps, le
*namespace* est libéré lorsque le dernier processus s'exécutant dedans se
termine.
Lorsque l'on a besoin de référencer un *namespace* (par exemple pour le faire
persister après le dernier processus), on peut utiliser un `mount bind` :
<div lang="en-US">
```bash
42sh# touch /tmp/ns/myrefns
42sh# mount --bind /proc/<PID>/ns/mount /tmp/ns/myrefns
```
</div>
De cette manière, même si le lien initial n'existe plus (si le `<PID>` s'est
terminé), `/tmp/ns/myrefns` pointera toujours au bon endroit.
Il est aussi tout à fait possible d'utiliser directement ce fichier pour
obtenir un descripteur de fichier valide vers le *namespace* (pour passer à
`setns(2)`).
::::: {.question}
#### Faire persister un *namespace* ? {-}
\
Il n'est pas possible de faire persister un espace de noms d'un reboot à
l'autre.\
Même en étant attaché à un fichier du disque, il s'agit d'un pointeur vers une
structure du noyau, qui ne persistera pas au redémarrage.
:::::

View File

@ -3,7 +3,10 @@
Des particularités de `mount` {#mount}
=============================
Petite parenthèse avant de parler des *namespaces* ...
Petite parenthèse avant de parler des *namespaces*, car nous avons encore
besoin d'appréhender un certain nombre de concepts relatifs aux montages de
systèmes de fichiers.
## Les points de montage
@ -19,7 +22,7 @@ deux endroits différents de votre arborescence ?
Si pour plein de raisons on pouvait se dire que cela ne devrait pas être
autorisé, ce problème s'avère être à la base de beaucoup de fonctionnalités
intéressantes. Le noyau va finalement décorréler les notions de montage,
d'accès et d'accroches dans l'arborescence : et par exemple, une partition ne
d'accès et d'accroche dans l'arborescence : et par exemple, une partition ne
sera plus forcément démontée après un appel à `umount(2)`, mais le sera
seulement lorsque cette partition n'aura plus d'accroches dans aucune
arborescence.
@ -59,7 +62,7 @@ TARGET SOURCE FSTYPE OPTIONS
```
</div>
## `bind`
## `bind` -- montage miroir
Lorsque l'on souhaite monter à un deuxième endroit (ou plus) une partition, on
utilise le *bind mount* :
@ -115,9 +118,9 @@ mount --rbind /sys sys
</div>
## Les montages parfumés
## Les types de propagation des points de montage
On distingue quatre variétés de répercution des montages pour un sous-arbre :
On distingue quatre variétés de propagation des montages pour un sous-arbre :
partagé, esclave, privé et non-attachable.
Chacun va agir sur la manière dont seront propagées les nouvelles accroches au
@ -232,7 +235,7 @@ mount --bind /mnt/test-slave /mnt/test-unbindable
</div>
### Parfums récursifs
### Propagation récursive
Les options que nous venons de voir s'appliquent sur un point de montage. Il
existe les mêmes options pour les appliquer en cascade sur les points d'attache
@ -248,7 +251,7 @@ mount --make-runbindable mountpoint
</div>
## `bind` de dossiers et de fichiers
## Montage miroir de dossiers et de fichiers
Il n'est pas nécessaire que le point d'accroche que l'on cherche à dupliquer
pointe sur un point de montage (c'est-à-dire, dans la plupart des cas : une
@ -258,7 +261,7 @@ que l'on pourrait faire entre plusieurs partitions et qui ne persisterait pas
au redémarrage (le *hardlink* persiste au redémarrage, mais doit se faire au
sein d'une même partition).
Nous verrons dans la partie [*namespace* réseau](#net-ns), une utilisation
Nous verrons dans la partie [*namespace* réseau](#net-ns) une utilisation
d'attache sur un fichier.

View File

@ -1,17 +1,33 @@
\newpage
Le *namespace* `mount`
======================
----------------------
L'espace de noms `mount` permet d'isoler la vision du système de fichiers
qu'ont un processus et ses fils.
Peut-être que l'on peut trouver avec ça, un moyen de faire un `chroot` plus sûr ?
::::: {.warning}
Attention il convient de prendre garde aux types de liaison existant entre vos
points de montage (voir la partie sur [les particularités des points de
montage](#mount)), car les montages et démontages pourraient alors être
répercutés dans l'espace de noms parent.\
## Préparation du changement de racine
Une manière rapide pour s'assurer que nos modifications ne sortiront pas de
notre *namespace* est d'appliquer le type esclave à l'ensemble de nos points de
montage, récursivement, dès que l'on est entré dans notre nouvel espace de
noms.
### Avant propos
<div lang="en-US">
```bash
mount --make-rslave /
```
</div>
:::::
### Préparation du changement de racine
Nous allons essayer de changer la racine de notre système de fichier. À la
différence d'un `chroot(2)`, changer de racine est quelque chose d'un peu plus
@ -29,7 +45,7 @@ montage virtuels. Le changement de racine sera donc effectif uniquement dans
cet espace de noms.
### L'environnement
#### L'environnement\
Pour pouvoir changer de racine, il est nécessaire que la nouvelle racine soit
la racine d'un point de montage, comme l'explique `pivot_root(2)`. En effet, il
@ -49,7 +65,7 @@ Placez ensuite dans cette nouvelle racine le système de votre choix (cf. le TP
précédent pour les différentes méthodes et liens).
## Changer de racine
### Exercice : Changer de racine -- `myswitch_root.sh`
Voici les grandes étapes du changement de racine :
@ -59,7 +75,7 @@ Voici les grandes étapes du changement de racine :
3. `pivot_root` !
### S'isoler
#### S'isoler\
Notre but étant de démonter toutes les partitions superflues, nous allons
devoir nous isoler sur :
@ -79,14 +95,14 @@ Isolons-nous :
</div>
### Dissocier la propagation des démontages
#### Dissocier la propagation des démontages\
Attention ! avant de pouvoir commencer à démonter les partitions, il faut
s'assurer que les démontages ne se propagent pas via une politique de *shared
mount*.
Commençons donc par étiqueter tous nos points de montage (de ce *namespace*),
comme esclave :
comme esclaves :
<div lang="en-US">
```bash
@ -95,26 +111,26 @@ comme esclave :
</div>
### Démonter tout !
#### Démonter tout !\
À vous maintenant de démonter vos points d'attache. Il ne devrait vous rester
après cette étape que : `/`, `/dev`, `/sys`, `/proc`, `/run` et leurs fils.
### Switch !
#### Switch !\
À ce stade, dans votre console, vous avez plusieurs solutions : utiliser
`switch_root(8)` ou `pivot_root(8)`. La première abstrait plus de choses que la
seconde.
#### `switch_root`
##### `switch_root`\
Cette commande s'occupe de déplacer les partitions restantes pour vous, et lance
la première commande (*init*) de votre choix.
#### `pivot_root`
##### `pivot_root`\
Cette commande, plus proche du fonctionnement de l'appel système
`pivot_root(2)`, requiert de notre part que nous ayons préalablement déplacé

View File

@ -0,0 +1,14 @@
### Aller plus loin {-}
Je vous recommande la lecture du *man* `namespaces(7)` introduisant et
énumérant les *namespaces*.
Pour tout connaître en détails, [la série d'articles de Michael Kerrisk sur les
*namespaces*](https://lwn.net/Articles/531114/) est excellente ! Auquel il faut
ajouter [l'article sur le plus récent `cgroup`
*namespace*](https://lwn.net/Articles/621006/) et [le petit dernier sur le
*namespace* `time`](https://lwn.net/Articles/766089/).
[Cet article de Michael Crosby montrant l'utilisation de clone(2)](https://web.archive.org/web/20190206073558/http://crosbymichael.com/creating-containers-part-1.html)
est également des plus intéressants, pour ce qui concerne la programmation
plus bas-niveau.

View File

@ -1,15 +1,15 @@
\newpage
Le *namespace* `network` {#net-ns}
========================
------------------------
## Introduction
### Introduction
L'espace de noms `network`, comme son nom l'indique permet de virtualiser tout
ce qui est en lien avec le réseau : les interfaces, les ports, les routes, les
règles de filtrage, etc.
En entrant dans un nouvel espace de nom `network`, on se retrouve dans un
En entrant dans un nouvel espace de noms `network`, on se retrouve dans un
environnement qui n'a plus qu'une interface de *loopback* :
<div lang="en-US">
@ -30,12 +30,12 @@ possible de lancer un serveur web sans qu'il n'entre en conflit avec celui d'un
autre espace de noms.
## Premiers pas avec `ip netns`
### Premiers pas avec `ip netns`
La suite d'outils `iproute2` propose une interface simplifiée pour utiliser le
*namespace* `network` : `ip netns`.
Nous pouvons tout d'abord créer un nouvel espace de nom :
Nous pouvons tout d'abord créer un nouvel espace de noms :
<div lang="en-US">
```bash
@ -84,7 +84,7 @@ PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
</div>
## *Virtual Ethernet*
### *Virtual Ethernet*
Étant donné qu'une interface réseau ne peut être présente que dans un seul
espace de noms à la fois, il n'est pas bien pratique d'imposer d'avoir une
@ -106,7 +106,7 @@ créé deux interfaces `veth0` et `veth1` : les paquets envoyés sur `veth0` son
donc reçus par `veth1` et les paquets envoyés à `veth1` sont reçus par `veth0`.
Dans cette configuration, ces deux interfaces ne sont pas très utiles, mais si
l'on place l'une des deux extrêmités dans un autre *namespace* `network`, il
l'on place l'une des deux extrémités dans un autre *namespace* `network`, il
devient alors possible de réaliser un échange de paquets entre les deux.
Pour déplacer `veth1` dans notre *namespace* `virli` :
@ -143,7 +143,7 @@ Il ne reste donc pas grand chose à faire pour fournir Internet à notre
conteneur : via un peu de NAT ou grâce à un pont Ethernet.
## Les autres types d'interfaces
### Les autres types d'interfaces
Le bridge ou le NAT obligera tous les paquets à passer à travers de nombreuses
couches du noyau. Utiliser les interfaces *veth* est plutôt simple et disponible
@ -151,7 +151,7 @@ partout, mais c'est loin d'être la technique la plus rapide ou la moins
gourmande.
### VLAN
#### VLAN\
Il est possible d'attribuer juste une interface de VLAN, si l'on a un switch
supportant la technologie [802.1q](https://fr.wikipedia.org/wiki/IEEE_802.1Q)
@ -166,7 +166,7 @@ derrière notre machine.
</div>
### MACVLAN
#### MACVLAN\
<!-- https://hicu.be/bridge-vs-macvlan -->
@ -175,12 +175,12 @@ les VLAN, le noyau met à disposition un routage basé sur les adresses MAC : le
MACVLAN. S'il est activé dans votre noyau, vous allez avoir le choix entre l'un
des quatre modes : *private*, VEPA, *bridge* ou *passthru*.
Quelque soit le mode choisi, les paquets en provenance d'autres machines et à
Quel que soit le mode choisi, les paquets en provenance d'autres machines et à
destination d'un MAC seront délivrés à l'interface possédant la MAC. Les
différences entre les modes se trouvent au niveau de la communication entre les
interfaces.
#### VEPA
##### VEPA
Dans ce mode, tous les paquets sortants sont directement envoyés sur
l'interface Ethernet de sortie, sans qu'aucun routage préalable n'ait été
@ -198,7 +198,7 @@ Pour construire une nouvelle interface de ce type :
</div>
#### *Private*
##### *Private*
À la différence du mode *VEPA*, si un paquet émis par un conteneur à
destination d'un autre conteneur est réfléchi par un switch, le paquet ne sera
@ -214,7 +214,7 @@ conteneur de la même machine.
</div>
#### *Bridge*
##### *Bridge*
À l'inverse des modes *VEPA* et *private*, les paquets sont routés selon leur
adresse MAC : si jamais une adresse MAC est connue, le paquet est délivré à
@ -230,12 +230,12 @@ Pour construire une nouvelle interface de ce type :
</div>
## Aller plus loin {-}
### Aller plus loin {-}
Pour approfondir les différentes techniques de routage, je vous
recommande cet article :
[Linux Containers and Networking](https://blog.flameeyes.eu/2010/09/linux-containers-and-networking).
Appliqué à Docker, vous apprécirez cet article : [Understanding Docker
Appliqué à Docker, vous apprécierez cet article : [Understanding Docker
Networking Drivers and their use
cases](https://www.docker.com/blog/understanding-docker-networking-drivers-use-cases/).

View File

@ -1,9 +1,9 @@
\newpage
Le *namespace* `PID` {#pid-ns}
=====================
--------------------
## Introduction {#pid-ns-intro}
### Introduction {#pid-ns-intro}
L'espace de noms `PID` est celui qui va nous permettre d'isoler un sous-arbre
de processus en créant un nouvel arbre, qui aura son propre processus considéré
@ -18,7 +18,7 @@ pas de PID en cours de route, puisqu'il dépend du *namespace* dans lequel il se
trouve.
## Isolons !
### Isolons !
Première étape s'isoler :
@ -32,7 +32,7 @@ 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)).
Un coup d'œil à `top` ou `ps aux` devrait nous montrer que l'on est maintenant
seul processus ... pourtant, il n'en est rien, ces deux commandes continuent
le seul processus ... pourtant, il n'en est rien, ces deux commandes continuent
d'afficher la liste complète des processus de notre système.
Cela est dû au fait que ces deux programmes, sous Linux, se basent sur le
@ -45,7 +45,7 @@ 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 :
@ -62,7 +62,7 @@ Cette fois, `top` et `ps` nous rapportent bien que l'on est seul dans notre
*namespace*.
## Arborescence à l'extérieur du *namespace*
### Arborescence à l'extérieur du *namespace*
Lors de notre première tentative de `top`, lorsque `/proc` était encore monté
sur le `procfs` de l'espace de noms initial : notre processus (au PID 1 dans
@ -79,14 +79,14 @@ parent, il faut le faire avec son identifiant de processus du même *namespace*
que le processus appelant.
## Processus orphelins et `nsenter`
### Processus orphelins et `nsenter`
Au sein d'un *namespace*, le processus au PID 1 est considéré comme le
programme `init`, les mêmes propriétés s'appliquent donc.
Si un processus est orphelin, il est donc affiché comme étant fils du PID 1
dans son *namespace*[^PR_SET_CHILD_SUBREAPER] ; il n'est pas sorti de l'espace
de nom.
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
@ -101,7 +101,7 @@ l'extérieur du conteneur, les propriétés d'`init` sont biens appliquées à
l'intérieur pour conserver un comportement cohérent.
## Aller plus loin {-}
### Aller plus loin {-}
N'hésitez pas à jeter un œil à la page de manuel consacré à cet espace de
N'hésitez pas à jeter un œil à la page de manuel consacrée à cet espace de
noms : `pid_namespaces(7)`.

View File

@ -3,16 +3,19 @@
Projet et rendu
===============
Projet
------
Est attendu d'ici le TP suivant :
[Le sujet complet du projet est disponible ici](https://virli.nemunai.re/project-3.pdf). Il
n'est pas à rendre en même temps que le TP. Consultez ses modalités de rendu
pour plus d'informations.
- le rendu des exercice de ce TP ;
- vos réponses à [l'évaluation du cours](https://virli.nemunai.re/quiz/15).
Pour les GISTRE (et en bonus pour les SRS), [un
projet](https://virli.nemunai.re/project-2.pdf) est à rendre pour le 13
novembre. Consultez les modalités de rendu sur le sujet directement.
Modalités de rendu
------------------
## Modalités de rendu
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP.
Un service automatique s'occupe de réceptionner vos rendus, de faire des
vérifications élémentaires et de vous envoyer un accusé de réception (ou de
@ -23,14 +26,11 @@ et exclusivement à celle-ci que vous devez envoyer vos rendus. Tout rendu
envoyé à une autre adresse et/ou non signé et/ou reçu après la correction ne
sera pas pris en compte.
Afin d'orienter correctement votre rendu, ajoutez une balise `[TP5]` au sujet
de votre courriel. N'hésitez pas à indiquer dans le corps du courriel votre
Afin d'orienter correctement votre rendu, ajoutez une balise `[TP4]` au sujet
de votre courriel. N'hésitez pas à indiquer dans le corps du message votre
ressenti et vos difficultés ou bien alors écrivez votre meilleure histoire
drôle si vous n'avez rien à dire.
Par ailleurs, n'oubliez pas de répondre à
[l'évaluation du cours](https://virli.nemunai.re/quiz/7).
Tarball
-------
@ -38,12 +38,14 @@ Tarball
Tous les exercices de ce TP sont à placer dans une tarball (pas d'archive ZIP,
RAR, ...).
Voici une arborescence type :
Voici une arborescence type (adaptez les extensions et les éventuels
fichiers supplémentaires associés au langage que vous aurez choisi
pour chaque exercice) :
<div lang="en-US">
```
login_x-TP5/cmpns.sh
login_x-TP5/mydocker_exec.sh
login_x-TP5/myswitch_root.sh
login_x-TP4/cmpns.sh
login_x-TP4/mydocker_exec.sh
login_x-TP4/myswitch_root.sh
```
</div>

View File

@ -0,0 +1,57 @@
#### Exemple C\
Voici un exemple de code C utilisant `setns(2)` :
<div lang="en-US">
```c
#define _GNU_SOURCE
#include <fcntl.h>
#include <sched.h>
#include <stdlib.h>
// ./a.out /proc/PID/ns/FILE cmd args...
int
main(int argc, char *argv[])
{
int fd = open(argv[1], O_RDONLY);
if (fd == -1)
{
perror("open");
return EXIT_FAILURE;
}
if (setns(fd, 0) == -1)
{
perror("setns");
return EXIT_FAILURE;
}
execvp(argv[2], &argv[2]);
perror("execve");
return EXIT_FAILURE;
}
```
</div>
#### Exemple shell\
Dans un shell, on utilisera la commande `nsenter(1)` :
<div lang="en-US">
```bash
42sh# unshare --uts /bin/bash
inutsns# echo $$
42
inutsns# hostname jument
# Keep this sheel active to perform nexts steps, in another shell.
42sh# hostname
chaton
42sh# nsenter --uts=/proc/42/ns/uts /bin/bash
inutsns# hostname
jument
```
</div>

67
tutorial/4/setns.md Normal file
View File

@ -0,0 +1,67 @@
\newpage
### Rejoindre un *namespace*
Rejoindre un espace de noms se fait en utilisant l'appel système `setns(2)`, ou
la commande `nsenter(1)`. Il est nécessaire de donner en argument
respectivement un *file descriptor* ou le chemin vers le fichier, lien
symbolique, représentant l'espace de nom.
#### Voir les *namespace*s d'un processus\
Chaque processus lancé est rattaché à une liste d'espaces de nom, y compris
s'il est issu du système de base (« l'hôte »).
Nous pouvons dès lors consulter le dossier `/proc/<PID>/ns/` de chaque
processus, pour consulter les différents espaces de nom de nos processus.
Tous les processus auront la même liste de fichiers, car ils sont liés à un
espace de noms par *namespace* utilisable avec le noyau. D'une machine à
l'autre, d'une version du noyau à l'autre, il est normal d'avoir une liste de
*namespace*s différents, mais d'un processus à l'autre sur le même noyau, nous
aurons les mêmes.
Ces fichiers sont en fait des liens symboliques un peu particuliers, car ils ne
pointent pas vers une destination valide :
<div lang="en-US">
```bash
42sh$ ls -l /proc/self/ns
lrwxrwxrwx 1 nemunaire 0 1 oct. 23:42 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx 1 nemunaire 0 1 oct. 23:42 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx 1 nemunaire 0 1 oct. 23:42 mnt -> 'mnt:[4026531840]'
lrwxrwxrwx 1 nemunaire 0 1 oct. 23:42 net -> 'net:[4026532008]'
lrwxrwxrwx 1 nemunaire 0 1 oct. 23:42 pid -> 'pid:[4026531836]'
lrwxrwxrwx 1 nemunaire 0 1 oct. 23:42 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx 1 nemunaire 0 1 oct. 23:42 time -> 'time:[4026531834]'
lrwxrwxrwx 1 nemunaire 0 1 oct. 23:42 time_for_children -> 'time:[4026531834]'
lrwxrwxrwx 1 nemunaire 0 1 oct. 23:42 user -> 'user:[4026531837]'
lrwxrwxrwx 1 nemunaire 0 1 oct. 23:42 uts -> 'uts:[4026531838]'
```
</div>
Les liens référencent une structure du noyau résidant en mémoire. Les numéros
entre crochets seront les mêmes pour deux processus qui partagent le même
espace de noms. La structure pointée sera différente si l'espace de nom est
différent, donc le numéro sera différent.
On ne peut pas afficher tel quel les structures, mais on peut l'ouvrir avec
`open(2)` pour obtenir un *file descriptor* que l'on pourra passer à
`setns(2)`.
Pour les commandes *shell*, il convient de donner en argument le chemin vers le
lien symbolique : la commande se chargera d'`open(2)` le fichier.
#### `*_for_children`\
Vous avez peut-être remarqué des fichiers `*_for_children` dans le dossier `ns`
de vos processus. Nous verrons par la suite que les espaces de noms *PID* et
*Time*, une fois créés, ne s'appliquent pas directement au processus en cours
d'exécution, la dissociation de *namespace* ne peut se faire que pour les
processus/threads fils.
`pid_for_children` et `time_for_children` représentent donc les *namespace*s
qui seront attribués aux fils lancés après un `unshare(2)` réussi.

View File

@ -1,14 +1,11 @@
\newpage
### Prérequis
Mise en place
=============
Noyau Linux
-----------
#### Noyau Linux \
Ce TP requiert un noyau Linux, dans sa version 3.12 au minimum. Il doit de plus
être compilé avec les options suivantes (lorsqu'elles sont disponibles pour
votre version) :
Pour pouvoir suivre les exercices ci-après, vous devez disposez d'un noyau
Linux, idéalement dans sa version 5.6 ou mieux. Il doit de plus être compilé
avec les options suivantes (lorsqu'elles sont disponibles pour votre version) :
<div lang="en-US">
```
@ -16,6 +13,7 @@ General setup --->
[*] Control Group support --->
-*- Namespaces support
[*] UTS namespace
[*] TIME namespace
[*] IPC namespace
[*] User namespace
[*] PID Namespaces
@ -38,6 +36,7 @@ CONFIG_CGROUPS=y
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
CONFIG_TIME_NS=y
CONFIG_IPC_NS=y
CONFIG_USER_NS=y
CONFIG_PID_NS=y
@ -52,11 +51,11 @@ CONFIG_VETH=m
```
</div>
Référez-vous, si besoin, au TP précédent pour la marche à suivre.
Référez-vous, si besoin, à la précédente configuration que l'on a faite pour la
marche à suivre.
Paquets
-------
#### Paquets \
Nous allons utiliser des programmes issus des
[`util-linux`](https://www.kernel.org/pub/linux/utils/util-linux/), de
@ -69,12 +68,18 @@ Sous Debian et ses dérivés, ces paquets sont respectivement :
* `procps`
* `libcap2-bin`
Sous ArchLinux et ses dérivés, ces paquets sont respectivement :
À propos de la sécurité de l'espace de nom `user`
-------------------------------------------------
* `util-linux`
* `procps-ng`
* `libcap`
La sécurité du *namespace* `user` a souvent été remise en cause et on lui
attribue de nombreuses vulnérabilités. Je vous laisse consulter à ce sujet :
#### À propos de la sécurité de l'espace de noms `user` \
La sécurité du *namespace* `user` a souvent été remise en cause par le passé,
on lui attribue de nombreuses vulnérabilités. Vous devriez notamment consulter
à ce sujet :
* [Security Implications of User Namespaces](https://blog.araj.me/security-implications-of-user-namespaces/) ;
* [Anatomy of a user namespaces vulnerability](https://lwn.net/Articles/543273/) ;
@ -84,13 +89,14 @@ attribue de nombreuses vulnérabilités. Je vous laisse consulter à ce sujet :
De nombreux projets ont choisi de ne pas autoriser l'utilisation de cet espace
de noms sans disposer de certaines *capabilities*[^userns-caps].
[^userns-caps]: Sont nécessaires, conjointement, `CAP_SYS_ADMIN`, `CAP_SETUID` et `CAP_SETGID`.
[^userns-caps]: Sont nécessaires, conjointement : `CAP_SYS_ADMIN`, `CAP_SETUID` et `CAP_SETGID`.
De nombreuses distributions ont par exemple choisi d'utiliser un paramètre du
noyau pour adapter le comportement.
De nombreuses distributions ont choisi d'utiliser un paramètre du noyau pour
adapter le comportement.
### Debian et ses dérivées {.unnumbered}
::::: {.question}
##### Debian et ses dérivées {.unnumbered}
Si vous utilisez Debian ou l'un de ses dérivés, vous devrez autoriser
explicitement cette utilisation non-privilégiée :
@ -102,12 +108,13 @@ explicitement cette utilisation non-privilégiée :
</div>
### Grsecurity {.unnumbered}
##### Grsecurity {.unnumbered}
D'autres patchs, tels que
[*grsecurity*](https://forums.grsecurity.net/viewtopic.php?f=3&t=3929#p13904) ont
fait le choix de désactiver cette possibilité sans laisser d'option pour la
réactiver éventuellement à l'exécution. Pour avoir un comportement identique à
celui de Debian, vous pouvez
[appliquer ce patch](https://virli.nemunai.re/grsec-enable-user-ns.patch), sur
[appliquer ce patch](https://virli.nemunai.re/grsec-enable-user-ns.patch) sur
vos sources incluant le patch de *grsecurity*.
:::::

View File

@ -13,7 +13,10 @@ abstract: |
\vspace{1em}
Tous les exercices de ce TP sont à rendre à <virli@nemunai.re> au
plus tard le jeudi 19 novembre 2020 à 12 h 42.
plus tard le mercredi 4 novembre 2021 à 23 h 42. Consultez la dernière
section de chaque partie pour plus d'informations sur les éléments à
rendre. Et n'oubliez pas de répondre aux [questions de
cours](https://virli.nemunai.re/quiz/13).
En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devrez m'envoyer vos rendus signés avec votre clef PGP. Pensez à

View File

@ -1,9 +1,9 @@
\newpage
Le *namespace* `user` {#user-ns}
=====================
---------------------
## Introduction
### Introduction
L'espace de noms `user` est plutôt pratique car il permet de virtualiser la
liste et les droits des utilisateurs.
@ -15,44 +15,44 @@ avoir besoin à l'intérieur de cet espace de noms, sans que cela ne réduise la
sécurité des composants à l'extérieur de cet espace.
## Comportement vis-à-vis des autres *namespaces*
### Comportement vis-à-vis des autres *namespaces*
Alors qu'il est normalement nécessaire d'avoir des privilèges pour créer de
nouveaux espaces de noms, en commençant par demander un *namespace*
utilisateurs, on obtient les privilèges requis pour créer tous les autres types
utilisateur, on obtient les privilèges requis pour créer tous les autres types
de *namespaces*.
Grâce à cette technique, il est possible de lancer des conteneurs en tant que
simple utilisateur ; le projet [Singularity](https://sylabs.io/) repose
entièrement sur cela.
en grande partie sur cela.
## Correspondance des utilisateurs et des groupes
### Correspondance des utilisateurs et des groupes
Comme pour les autres espaces de noms, le *namespace* `user` permet de ne
garder dans le nouvel espace, que les utilisateurs et les groupes utiles au
processus, en les renumérotant au passage si besoin.
### L'utilisateur -2 : *nobody*
#### L'utilisateur -2 : *nobody*\
Lorsque l'on arrive dans un nouvel espace, aucun utilisateur ni groupe n'est
défini. Dans cette situation, tous les identifiants d'utilisateur et de groupe,
renvoyés par le noyau sont à -2 ; valeur qui correspond par convention à
l'utilisateur *nobody* et au groupe *nogroup*.
-1 étant réservé pour indiqué une erreur dans le retour d'une commande, ou la
non-modification d'un paramètres passé en argument d'une fonction.
-1 étant réservé pour indiquer une erreur dans le retour d'une commande, ou la
non-modification d'un paramètre passé en argument d'une fonction.
### `uid_map` et `gid_map`
#### `uid_map`
#### `uid_map` et `gid_map` \
Pour établir la correspondance, une fois que l'on a créé le nouveau
*namespace*, ces deux fichiers, accessibles dans `/proc/self/`, peuvent être
écrits une fois.
##### `uid_map`\
Sur chaque ligne, on doit indiquer :
- L'identifiant marquant le début de la plage d'utilisateurs, pour le processus
@ -72,8 +72,8 @@ Par exemple, le *namespace* `user` initial défini la correspondance suivante :
</div>
Cela signifie que les utilisateurs dont l'identifiant court de 0 à `MAX_INT -
2` inclu, dans cet espace de noms, correspondent aux utilisateurs allant de 0 à
`MAX_INT - 1` inclu, pour le processus affichant ce fichier.
2` inclus, dans cet espace de noms, correspondent aux utilisateurs allant de 0 à
`MAX_INT - 1` inclus, pour le processus affichant ce fichier.
Lorsque l'on crée un *namespace* `user`, généralement, la correspondance vaut :
@ -89,13 +89,13 @@ l'utilisateur root, dans le conteneur équivaut à l'utilisateur 1000 hors de
l'espace de noms.
#### `gid_map`
##### `gid_map`\
Le principe est identique pour ce fichier, mais agit sur les correspondances
des groupes au lieu des utilisateurs.
## Utilisation de l'espace de noms
### Utilisation de l'espace de noms
<div lang="en-US">
```bash
@ -110,7 +110,7 @@ jeu. L'idée étant que l'on a été désigné root dans son conteneur, on devra
pouvoir y faire ce que l'on veut, tant que l'on n'agit pas en dehors.
## Aller plus loin {-}
### Aller plus loin {-}
N'hésitez pas à jeter un œil à la page du manuel consacré à ce *namespace* :
N'hésitez pas à jeter un œil à la page du manuel consacrée à ce *namespace* :
`user_namespaces(7)`.