Save tuto corrections

This commit is contained in:
nemunaire 2022-02-24 20:43:43 +01:00
commit 10448a6c8d
115 changed files with 1423 additions and 1289 deletions

View file

@ -1,6 +1,6 @@
\newpage
### Exercice : comparaison de *namespace* -- `cmpns.sh`
### 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/`.
@ -46,9 +46,9 @@ que l'on cherche à comparer.
Ici, `self` fait référence au processus actuellement exécuté (comme il existe
un dossier `/proc/self/`, vous n'avez pas besoin de gérer de cas particulier
pour ça !).
pour ça !).
Et pourquoi pas :
Et pourquoi pas :
<div lang="en-US">
```

View file

@ -1,19 +1,19 @@
\newpage
Exercice : `docker exec`
Exercice : `docker exec`
------------------------
Après voir lu la partie concernant les *namespaces*, vous avez dû comprendre
qu'un `docker exec`, n'était donc rien de plus qu'un `nsenter(1)`.
Réécrivons, en quelques lignes, la commande `docker exec` !
Réécrivons, en quelques lignes, la commande `docker exec` !
Pour savoir si vous avez réussi, comparez les sorties des commandes :
Pour savoir si vous avez réussi, comparez les sorties des commandes :
- `ip address` ;
- `hostname` ;
- `mount` ;
- `pa -aux` ;
- `ip address` ;
- `hostname` ;
- `mount` ;
- `ps -aux` ;
- ...
@ -27,11 +27,11 @@ d63ceae863956f8312aca60b7a57fbcc1fdf679ae4c90c5d9455405005d4980a
234269
42sh# ./mydocker_exec mywebserver ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group def
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP group def
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.1/16 scope global eth0
valid_lft forever preferred_lft forever

View file

@ -33,7 +33,7 @@ En fonction des options qui lui sont passées, `unshare(1)` va créer le/les
nouveaux *namespaces* et placer le processus dedans.
Par exemple, nous pouvons modifier sans crainte le nom de notre machine, si
nous sommes passés dans un autre *namespace* `UTS` :
nous sommes passés dans un autre *namespace* `UTS` :
<div lang="en-US">
```
@ -64,7 +64,7 @@ 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 :
sont passés :
* `CLONE_NEWNS`,
* `CLONE_NEWUTS`,
@ -83,7 +83,7 @@ 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 C
semblable à :
semblable à :
<div lang="en-US">
```c
@ -118,7 +118,7 @@ dans un nouvel espace de noms. Dans ce cas, on utilisera l'appel système
::::: {.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 !
et *Time* n'est pas celui que l'on peut attendre !
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 à

View file

@ -22,12 +22,12 @@ 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`,
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
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, ...).
@ -74,12 +74,12 @@ 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
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
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.
@ -89,7 +89,7 @@ processus, et non un fils de l'`init` de l'arbre global.
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
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
@ -126,7 +126,7 @@ 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
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.

View file

@ -11,7 +11,7 @@ de processus qui l'utilisent. C'est-à-dire que, la plupart du temps, le
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` :
persister après le dernier processus), on peut utiliser un `mount bind` :
<div lang="en-US">
```bash
@ -29,7 +29,7 @@ obtenir un descripteur de fichier valide vers le *namespace* (pour passer à
::::: {.question}
#### Faire persister un *namespace* ? {-}
#### Faire persister un *namespace* ? {-}
\
Il n'est pas possible de faire persister un espace de noms d'un reboot à

View file

@ -6,7 +6,7 @@ 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 ?
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
@ -33,7 +33,7 @@ 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
sportif car il s'agit de ne plus avoir aucune trace de l'ancienne racine. Au
moins ici, il ne sera certainement pas possible de revenir en arrière dans
l'arborescence\ !
l'arborescence !
Pour l'instant, votre système utilise sans doute la partition d'un disque
physique comme racine de son système de fichier. Le changement de racine, va
@ -52,7 +52,7 @@ la racine d'un point de montage, comme l'explique `pivot_root(2)`. En effet, il
serait encore possible hypothétiquement de remonter dans l'arborescence si l'on
ne se trouvait pas à la racine d'une partition au moment du basculement.
Si vous n'avez pas de partition à disposition, vous pouvez utiliser un `tmpfs` :
Si vous n'avez pas de partition à disposition, vous pouvez utiliser un `tmpfs` :
<div lang="en-US">
```bash
@ -61,32 +61,31 @@ Si vous n'avez pas de partition à disposition, vous pouvez utiliser un `tmpfs`
```
</div>
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).
Placez ensuite dans cette nouvelle racine le système de votre choix.
### Exercice : Changer de racine -- `myswitch_root.sh`
### Exercice : Changer de racine -- `myswitch_root.sh`
Voici les grandes étapes du changement de racine :
Voici les grandes étapes du changement de racine :
1. S'isoler dans les *namespaces* adéquats ;
1. S'isoler dans les *namespaces* adéquats ;
2. Démonter ou déplacer toutes les partitions de l'ancienne racine vers la
nouvelle racine ;
3. `pivot_root` !
nouvelle racine ;
3. `pivot_root` !
#### S'isoler\
Notre but étant de démonter toutes les partitions superflues, nous allons
devoir nous isoler sur :
devoir nous isoler sur :
* les points de montages, ça semble évident ;
* les PIDs : car on ne pourra pas démonter une partition en cours
* les points de montages, ça semble évident ;
* les PIDs : car on ne pourra pas démonter une partition en cours
d'utilisation. S'il n'y a pas de processus, il n'y a personne pour nous
empêcher de démonter une partition !
empêcher de démonter une partition !
* les autres *namespaces* ne sont pas forcément nécessaires.
Isolons-nous :
Isolons-nous :
<div lang="en-US">
```bash
@ -97,12 +96,12 @@ Isolons-nous :
#### Dissocier la propagation des démontages\
Attention ! avant de pouvoir commencer à démonter les partitions, il faut
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 esclaves :
comme esclaves :
<div lang="en-US">
```bash
@ -111,15 +110,15 @@ comme esclaves :
</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.
après cette étape que : `/`, `/dev`, `/sys`, `/proc`, `/run` et leurs fils.
#### Switch !\
#### Switch !\
À ce stade, dans votre console, vous avez plusieurs solutions : utiliser
À 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.
@ -136,7 +135,7 @@ 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é
les partitions systèmes à leur place dans la nouvelle racine.
L'appel de la commande sert à intervertir les deux racines ; elle prend en argument :
L'appel de la commande sert à intervertir les deux racines ; elle prend en argument :
* le chemin de la nouvelle racine,
* le chemin dans la nouvelle racine où placer l'ancienne.
@ -144,7 +143,7 @@ L'appel de la commande sert à intervertir les deux racines ; elle prend en argu
Une fois le pivot effectué, on peut démonter l'ancienne racine.
Pour lancer la première commande dans la nouvelle racine, on passe généralement
par :
par :
<div lang="en-US">
```bash

View file

@ -4,7 +4,7 @@ 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
*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/).

View file

@ -6,11 +6,11 @@ Le *namespace* `network` {#net-ns}
### 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
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 noms `network`, on se retrouve dans un
environnement qui n'a plus qu'une interface de *loopback* :
environnement qui n'a plus qu'une interface de *loopback* :
<div lang="en-US">
```
@ -25,7 +25,7 @@ environnement principal, il s'agit bien de deux interfaces isolées l'une de
l'autre.
Qui dit nouvelle pile réseau, dit également que les ports qui sont assignés
dans l'espace principal, ne le sont plus dans le conteneur : il est donc
dans l'espace principal, ne le sont plus dans le conteneur : il est donc
possible de lancer un serveur web sans qu'il n'entre en conflit avec celui d'un
autre espace de noms.
@ -33,9 +33,9 @@ autre espace de noms.
### Premiers pas avec `ip netns`
La suite d'outils `iproute2` propose une interface simplifiée pour utiliser le
*namespace* `network` : `ip netns`.
*namespace* `network` : `ip netns`.
Nous pouvons tout d'abord créer un nouvel espace de noms :
Nous pouvons tout d'abord créer un nouvel espace de noms :
<div lang="en-US">
```bash
@ -45,17 +45,17 @@ Nous pouvons tout d'abord créer un nouvel espace de noms :
La technique utilisée ici pour avoir des *namespaces* nommés est la même que
celle que nous avons vue dans
[la première partie sur les *namespaces*](#ns-lifetime) : via un `mount --bind`
[la première partie sur les *namespaces*](#ns-lifetime) : via un `mount --bind`
dans le dossier `/var/run/netns/`. Cela permet de faire persister le namespace
malgré le fait que plus aucun processus ne s'y exécute.
Maintenant que notre *namespace* est créé, nous pouvons regarder s'il contient
des interfaces :
des interfaces :
<div lang="en-US">
```
42sh# ip netns exec virli ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1
1: lo: <LOOPBACK> mut 65536 qdisc noop state DOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
```
</div>
@ -64,7 +64,7 @@ Cette commande ne nous montre que l'interface de *loopback*, car nous n'avons
pour l'instant pas encore attaché la moindre interface.
D'ailleurs, cette interface est rapportée comme étant désactivée, activons-là
via la commande :
via la commande :
<div lang="en-US">
```bash
@ -92,7 +92,7 @@ interface physique par conteneur, d'autant plus si l'on a plusieurs
centaines de conteneurs à gérer.
Une technique couramment employée consiste à créer une interface virtuelle de
type `veth` :
type `veth` :
<div lang="en-US">
```
@ -100,16 +100,16 @@ type `veth` :
```
</div>
Une interface `veth` se comporte comme un tube bidirectionnel : tout ce qui
Une interface `veth` se comporte comme un tube bidirectionnel : tout ce qui
entre d'un côté sort de l'autre et inversement. La commande précédente a donc
créé deux interfaces `veth0` et `veth1` : les paquets envoyés sur `veth0` sont
créé deux interfaces `veth0` et `veth1` : les paquets envoyés sur `veth0` sont
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
devient alors possible de réaliser un échange de paquets entre les deux.
Pour déplacer `veth1` dans notre *namespace* `virli` :
Pour déplacer `veth1` dans notre *namespace* `virli` :
<div lang="en-US">
```bash
@ -117,7 +117,7 @@ Pour déplacer `veth1` dans notre *namespace* `virli` :
```
</div>
Il ne reste maintenant plus qu'à assigner une IP à chacune des interfaces :
Il ne reste maintenant plus qu'à assigner une IP à chacune des interfaces :
<div lang="en-US">
```bash
@ -126,7 +126,7 @@ Il ne reste maintenant plus qu'à assigner une IP à chacune des interfaces :
```
</div>
Dès lors[^linkdown], nous pouvons `ping`er chaque extrêmité :
Dès lors[^linkdown], nous pouvons `ping`er chaque extrêmité :
[^linkdown]: Il peut être nécessaire d'activer chaque lien, via `ip link set
vethX up`.
@ -140,7 +140,7 @@ Dès lors[^linkdown], nous pouvons `ping`er chaque extrêmité :
</div>
Il ne reste donc pas grand chose à faire pour fournir Internet à notre
conteneur : via un peu de NAT ou grâce à un pont Ethernet.
conteneur : via un peu de NAT ou grâce à un pont Ethernet.
### Les autres types d'interfaces
@ -171,9 +171,9 @@ derrière notre machine.
<!-- https://hicu.be/bridge-vs-macvlan -->
Lorsque l'on n'a pas assez de carte ethernet et que le switch ne supporte pas
les VLAN, le noyau met à disposition un routage basé sur les adresses MAC : le
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*.
des quatre modes : *private*, VEPA, *bridge* ou *passthru*.
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
@ -189,7 +189,7 @@ la machine, c'est à l'équipement réseau derrière la machine de rerouter le
paquet vers la machine émettrice (par exemple un switch
[802.1Qbg](http://www.ieee802.org/1/pages/802.1bg.html)).
Pour construire une nouvelle interface de ce type :
Pour construire une nouvelle interface de ce type :
<div lang="en-US">
```
@ -217,11 +217,11 @@ conteneur de la même machine.
##### *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é à
l'interface MACVLAN correspondante ; dans le cas contraire, le paquet est
adresse MAC : si jamais une adresse MAC est connue, le paquet est délivré à
l'interface MACVLAN correspondante ; dans le cas contraire, le paquet est
envoyé sur l'interface de sortie.
Pour construire une nouvelle interface de ce type :
Pour construire une nouvelle interface de ce type :
<div lang="en-US">
```
@ -233,9 +233,9 @@ Pour construire une nouvelle interface de ce type :
### Aller plus loin {-}
Pour approfondir les différentes techniques de routage, je vous
recommande cet article :
recommande cet article :
[Linux Containers and Networking](https://blog.flameeyes.eu/2010/09/linux-containers-and-networking).
Appliqué à Docker, vous apprécierez 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

@ -18,9 +18,9 @@ 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 :
Première étape s'isoler :
<div lang="en-US">
```bash
@ -45,9 +45,9 @@ 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 :
Voici la nouvelle ligne de commande que l'on va utiliser :
<div lang="en-US">
```bash
@ -65,11 +65,11 @@ Cette fois, `top` et `ps` nous rapportent bien que l'on est seul dans notre
### 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
sur le `procfs` de l'espace de noms initial : notre processus (au PID 1 dans
son nouveau *namespace*) était présent dans l'arborescence de l'espace initial
avec un PID dans la continuité des autres processus, étonnant !
avec un PID dans la continuité des autres processus, étonnant !
En fait, l'isolation consiste en une virtualisation des numéros du processus :
En fait, l'isolation consiste en une virtualisation des numéros du processus :
la plupart des processus du système initial ne sont pas accessibles, et ceux qui
font partie de l'espace de noms créé disposent d'une nouvelle numérotation. Et
c'est cette nouvelle numérotation qui est montrée au processus.
@ -85,12 +85,12 @@ 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
dans son *namespace*[^PR_SET_CHILD_SUBREAPER] ; il n'est pas sorti de l'espace
de noms.
[^PR_SET_CHILD_SUBREAPER]: en réalité, ce comportement est lié à la propriété
`PR_SET_CHILD_SUBREAPER`, qui peut être définie pour n'importe quel processus
de l'arborescence. Le processus au PID 1 hérite forcément de cette propriété\ ;
de l'arborescence. Le processus au PID 1 hérite forcément de cette propriété\ ;
il va donc récupérer tous les orphelins, si aucun de leurs parents n'ont la
propriété définie.
@ -104,4 +104,4 @@ l'intérieur pour conserver un comportement cohérent.
### Aller plus loin {-}
N'hésitez pas à jeter un œil à la page de manuel consacrée à cet espace de
noms : `pid_namespaces(7)`.
noms : `pid_namespaces(7)`.

View file

@ -9,7 +9,7 @@ Projet et rendu
notation de ce cours.**
Vous allez continuer aujourd'hui le projet qui s'étendra depuis le TP précédent
et qui consistera à réaliser la partie d'isolation de la moulinette des ACUs !
et qui consistera à réaliser la partie d'isolation de la moulinette des ACUs !
Cette semaine, il faudra faire en sorte de restreindre un groupe de processus
pour qu'il s'exécute indépendemment de votre système.
@ -17,8 +17,8 @@ pour qu'il s'exécute indépendemment de votre système.
Il n'y a pas de restriction sur le langage utilisé, vous pouvez tout aussi bien
utiliser du C, du C++, du Python, du shell, etc.
L'usage de bibliothèques **non relatives** au projet est autorisé : le but de
L'usage de bibliothèques **non relatives** au projet est autorisé : le but de
ce sujet est d'évaluer votre compréhension et votre utilisation de la
tuyauterie bas-niveau du noyau liée à la virtualisation légère. À partir du
moment où vous n'utilisez pas une bibliothèque qui abstrait complètement cette
plomberie, n'hésitez pas à l'utiliser !
plomberie, n'hésitez pas à l'utiliser !

View file

@ -3,9 +3,9 @@
Projet et rendu
===============
Est attendu d'ici le TP suivant :
Est attendu d'ici le TP suivant :
- le rendu des exercice de ce TP ;
- 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
@ -40,7 +40,7 @@ RAR, ...).
Voici une arborescence type (adaptez les extensions et les éventuels
fichiers supplémentaires associés au langage que vous aurez choisi
pour chaque exercice) :
pour chaque exercice) :
<div lang="en-US">
```

View file

@ -1,6 +1,6 @@
#### Exemple C\
Voici un exemple de code C utilisant `setns(2)` :
Voici un exemple de code C utilisant `setns(2)` :
<div lang="en-US">
```c
@ -38,7 +38,7 @@ main(int argc, char *argv[])
#### Exemple shell\
Dans un shell, on utilisera la commande `nsenter(1)` :
Dans un shell, on utilisera la commande `nsenter(1)` :
<div lang="en-US">
```bash

View file

@ -23,7 +23,7 @@ l'autre, d'une version du noyau à l'autre, il est normal d'avoir une liste de
aurons les mêmes.
Ces fichiers sont en fait des liens symboliques un peu particuliers, car ils ne
pointent pas vers une destination valide :
pointent pas vers une destination valide :
<div lang="en-US">
```bash
@ -52,7 +52,7 @@ On ne peut pas afficher tel quel les structures, mais on peut l'ouvrir avec
`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.
lien symbolique : la commande se chargera d'`open(2)` le fichier.
#### `*_for_children`\

View file

@ -5,7 +5,7 @@
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) :
avec les options suivantes (lorsqu'elles sont disponibles pour votre version) :
<div lang="en-US">
```
@ -28,7 +28,7 @@ Device Drivers --->
```
</div>
Les variables de configuration correspondantes sont :
Les variables de configuration correspondantes sont :
<div lang="en-US">
```
@ -62,13 +62,13 @@ Nous allons utiliser des programmes issus des
[`procps-ng`](https://gitlab.com/procps-ng/procps) ainsi que ceux de la
[`libcap`](https://sites.google.com/site/fullycapable/).
Sous Debian et ses dérivés, ces paquets sont respectivement :
Sous Debian et ses dérivés, ces paquets sont respectivement :
* `util-linux`
* `procps`
* `libcap2-bin`
Sous ArchLinux et ses dérivés, ces paquets sont respectivement :
Sous ArchLinux et ses dérivés, ces paquets sont respectivement :
* `util-linux`
* `procps-ng`
@ -79,17 +79,17 @@ Sous ArchLinux et ses dérivés, ces paquets sont respectivement :
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 :
à 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/) ;
* <http://marc.info/?l=linux-kernel&m=135543612731939&w=2> ;
* [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/) ;
* <http://marc.info/?l=linux-kernel&m=135543612731939&w=2> ;
* <http://marc.info/?l=linux-kernel&m=135545831607095&w=2>.
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 choisi d'utiliser un paramètre du noyau pour
adapter le comportement.
@ -99,7 +99,7 @@ adapter le comportement.
##### 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 :
explicitement cette utilisation non-privilégiée :
<div lang="en-US">
```bash

View file

@ -23,7 +23,7 @@ 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
simple utilisateur ; le projet [Singularity](https://sylabs.io/) repose
en grande partie sur cela.
@ -34,11 +34,11 @@ 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 à
renvoyés par le noyau sont à -2 ; valeur qui correspond par convention à
l'utilisateur *nobody* et au groupe *nogroup*.
-1 étant réservé pour indiquer une erreur dans le retour d'une commande, ou la
@ -53,7 +53,7 @@ Pour établir la correspondance, une fois que l'on a créé le nouveau
##### `uid_map`\
Sur chaque ligne, on doit indiquer :
Sur chaque ligne, on doit indiquer :
- L'identifiant marquant le début de la plage d'utilisateurs, pour le processus
en question.
@ -62,7 +62,7 @@ Sur chaque ligne, on doit indiquer :
- La taille de la plage.
Par exemple, le *namespace* `user` initial défini la correspondance suivante :
Par exemple, le *namespace* `user` initial défini la correspondance suivante :
<div lang="en-US">
```
@ -75,7 +75,7 @@ Cela signifie que les utilisateurs dont l'identifiant court de 0 à `MAX_INT -
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 :
Lorsque l'on crée un *namespace* `user`, généralement, la correspondance vaut :
<div lang="en-US">
```
@ -99,18 +99,18 @@ des groupes au lieu des utilisateurs.
<div lang="en-US">
```bash
42sh$ unshare --mount --pid --mount-proc --fork --net --user --map-root-user /bin/bash
42sh$ unshare --mount --pid --mount-proc --fork --net --user --map-root-user bash
```
</div>
Un `capsh --print` nous montre que l'on est bien `root` et que l'on possède
toutes les *capabilities*. Cependant, cela ne signifie pas que l'on a tous les
droits sur le système ; il y a plusieurs niveaux de validation qui entrent en
droits sur le système ; il y a plusieurs niveaux de validation qui entrent en
jeu. L'idée étant que l'on a été désigné root dans son conteneur, on devrait
pouvoir y faire ce que l'on veut, tant que l'on n'agit pas en dehors.
### Aller plus loin {-}
N'hésitez pas à jeter un œil à la page du manuel consacrée à ce *namespace* :
N'hésitez pas à jeter un œil à la page du manuel consacrée à ce *namespace* :
`user_namespaces(7)`.