Save tuto corrections
This commit is contained in:
parent
f5ee6b8534
commit
10448a6c8d
115 changed files with 1425 additions and 1291 deletions
|
@ -35,7 +35,7 @@ On trouve par exemple :
|
|||
Pour émettre un ping, il est nécessaire d'envoyer des paquets ICMP. À la
|
||||
différence des datagrammes UDP ou des segments TCP, il n'est pas forcément
|
||||
simple d'envoyer des paquets ICMP lorsque l'on est simple utilisateur, car
|
||||
l'usage du protocole ICMP dans une socket est restreint : il faut soit être
|
||||
l'usage du protocole ICMP dans une soket est restreint : il faut soit être
|
||||
super-utilisateur, soit que le noyau ait été configuré pour autoriser certains
|
||||
utilisateurs à envoyer des `ECHO_REQUEST`.
|
||||
|
||||
|
@ -64,7 +64,7 @@ se mettent à fournir par défaut une configuration qui permette de se passer de
|
|||
*capabilities* pour lancer `ping`.\
|
||||
|
||||
Si vous vous rendez compte que votre binaire `ping` est dans ce cas, testez
|
||||
depuis un conteneur, par exemple :
|
||||
depuis un conteneur, par exemple :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
|
@ -83,7 +83,7 @@ depuis un conteneur, par exemple :
|
|||
</div>
|
||||
|
||||
Dans le conteneur le binaire `ping` est *setuid root*, vous pouvez faire des
|
||||
tests en retirant le *setuid* :
|
||||
tests en retirant le *setuid* :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
|
@ -94,7 +94,7 @@ tests en retirant le *setuid* :
|
|||
```
|
||||
</div>
|
||||
|
||||
Puis en ajoutant la *capability* :
|
||||
Puis en ajoutant la *capability* :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
### Exercice (obligatoire pour les SRS -- optionnel pour les GISTRE)
|
||||
|
||||
Poursuivons [notre script de monitoring](#script-monitoring) afin d'envoyer nos
|
||||
résultats vers InfluxDB : nous l'appellerons `./telegraf.sh`
|
||||
résultats vers InfluxDB : nous l'appellerons `./telegraf.sh`.
|
||||
|
||||
#### Rappel d'InfluxDB\
|
||||
|
||||
Commençons par lancer le conteneur Docker d'InfluxDB (pour éviter de
|
||||
l'installer sur notre machine) :
|
||||
l'installer sur notre machine) :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -16,7 +16,7 @@ docker container run --name mytsdb -d -p 8086:8086 influxdb:1.8
|
|||
|
||||
Il nous faut ensuite créer une base de données pour y stocker nos
|
||||
métriques. Voici comment on s'était débrouillé précédemment pour interagir avec
|
||||
InfluxDB :
|
||||
InfluxDB :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -33,7 +33,7 @@ Vérifiez que la base de données `metrics` a bien été créée.
|
|||
#### Monitoring vers InfluxDB\
|
||||
|
||||
Maintenant, envoyons nos données vers la base
|
||||
<https://docs.influxdata.com/influxdb/v1.8/guides/write_data/> :
|
||||
<https://docs.influxdata.com/influxdb/v1.8/guides/write_data/> :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -43,7 +43,7 @@ curl -i -XPOST 'http://localhost:8086/write?db=metrics' --data-binary \
|
|||
</div>
|
||||
|
||||
Pour vérifier que les données ont bien été ajoutées, nous pouvons effectuer la
|
||||
requête suivante dans notre client `influx` :
|
||||
requête suivante dans notre client `influx` :
|
||||
|
||||
<div lang="en-US">
|
||||
```sql
|
||||
|
@ -54,15 +54,15 @@ SELECT * from "$my_cgroup_name";
|
|||
|
||||
#### Monitorer davantage de données\
|
||||
|
||||
Liste non exhaustive de données à monitorer :
|
||||
Liste non exhaustive de données à monitorer :
|
||||
|
||||
* Nombre d'IOs effectué ;
|
||||
* nombre d'octets lus/écrits sur les disques ;
|
||||
* temps de calcul utilisé (`userspace`, `system`, tout confondu) ;
|
||||
* Nombre d'IOs effectué ;
|
||||
* nobre d'octets lus/écrits sur les disques ;
|
||||
* temps de calcul utilisé (`userspace`, `system`, tout confondu) ;
|
||||
* ...
|
||||
|
||||
Tous les cgroups existants dans le dernier noyau publié ont leur documentation
|
||||
accessible ici :
|
||||
accessible ici :
|
||||
|
||||
- v1 : <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/index.html>
|
||||
- v2 : <https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html>
|
||||
|
|
|
@ -4,40 +4,40 @@ Les *cgroup*s
|
|||
-------------
|
||||
|
||||
Les *cgroup*s (pour *Control Group*s) permettent de collecter des statistiques
|
||||
sur des **groupes de processus** (voire même, des threads !) et de leur
|
||||
sur des **groupes de processus** (voire même, des threads !) et de leur
|
||||
attribuer des propriétés. Il est par exemple possible de leur imposer des
|
||||
limites d'utilisation de ressources ou d'altérer leur comportement : quantité
|
||||
limites d'utilisation de ressources ou d'altérer leur comportement : quantité
|
||||
de RAM, temps CPU, bande passante, ...
|
||||
|
||||
Apparue dès [Linux
|
||||
2.6.24](https://kernelnewbies.org/Linux_2_6_24#Task_Control_Groups)
|
||||
(en 2008 !), les *cgroup*s sont répartis en différents sous-systèmes
|
||||
(en 2008 !), les *cgroup*s sont répartis en différents sous-systèmes
|
||||
(*subsystem*), chacun étant responsable d'un type de ressources
|
||||
spécifique :
|
||||
spécifique :
|
||||
|
||||
- [`blkio` (`io` dans la v2)
|
||||
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/blkio-controller.html)
|
||||
limites et statistiques de bande passante sur les disques ;
|
||||
- `cpu` : cycles CPU minimum garantis ;
|
||||
limites et statistiques de bande passante sur les disques ;
|
||||
- `cpu` : cycles CPU minimum garantis ;
|
||||
- [`cpuacct` (inclus dans `cpu` dans la v2)
|
||||
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpuacct.html)
|
||||
statistiques du temps CPU utilisé ;
|
||||
statistiques du temps CPU utilisé ;
|
||||
- [`cpuset`
|
||||
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpusets.html)
|
||||
associe des tâches à un/des CPU particuliers (par exemple pour dédier un cœur
|
||||
du CPU à un programme, qui ne pourra alors utiliser que ce CPU et pas les
|
||||
autres) ;
|
||||
autres) ;
|
||||
- [`devices`
|
||||
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/devices.html)
|
||||
règles de contrôle de création (`mknod`) et d'accès aux périphériques ;
|
||||
règles de contrôle de création (`mknod`) et d'accès aux périphériques ;
|
||||
- [`freezer`
|
||||
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/freezer-subsystem.html)
|
||||
pour suspendre et reprendre l'exécution d'un groupe de tâches ;
|
||||
- [`hugetlb` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/hugetlb.html) statistiques et limitation de l'usage de la fonctionnalité `HugeTLB` (permettant d'obtenir des pages mémoires plus grande que 4 kB) ;
|
||||
- [`memory` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/memory.html) statistiques et limitation d'usage de la mémoire vive et de la *swap* ;
|
||||
- [`net_cls` (v1 seulement) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/net_cls.html) applique un `classid` à tous les paquets émis par les tâches du *cgroup*, pour filtrage par le pare-feu en sortie ;
|
||||
- [`net_prio` (v1 seulement) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/net_prio.html) surcharge la valeur de l'option de priorité `SO_PRIORITY`, ordonant la file d'attente des paquets sortants ;
|
||||
- [`pids` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/pids.html) statistiques et limitation du nombre de processus ;
|
||||
pour suspendre et reprendre l'exécution d'un groupe de tâches ;
|
||||
- [`hugetlb` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/hugetlb.html) statistiques et limitation de l'usage de la fonctionnalité `HugeTLB` (permettant d'obtenir des pages mémoires plus grande que 4 kB) ;
|
||||
- [`memory` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/memory.html) statistiques et limitation d'usage de la mémoire vive et de la *swap* ;
|
||||
- [`net_cls` (v1 seulement) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/net_cls.html) applique un `classid` à tous les paquets émis par les tâches du *cgroup*, pour filtrage par le pare-feu en sortie ;
|
||||
- [`net_prio` (v1 seulement) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/net_prio.html) surcharge la valeur de l'option de priorité `SO_PRIORITY`, ordonant la file d'attente des paquets sortants ;
|
||||
- [`pids` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/pids.html) statistiques et limitation du nombre de processus ;
|
||||
- ...
|
||||
|
||||
Nous allons commencer par faire quelques tests avec le *cgroup* *freezer*, qui
|
||||
|
@ -48,19 +48,19 @@ lorsqu'on le décide.
|
|||
### Montage du *freezer*
|
||||
|
||||
En fonction de la configuration de votre système, vous allez vous trouver dans
|
||||
l'une de ces trois situations :
|
||||
l'une de ces trois situations :
|
||||
|
||||
- Votre dossier `/sys/fs/cgroup` contient à la fois des fichiers `cgroup.*` et
|
||||
éventuellement des dossiers : vous avez une distribution moderne qui utilise
|
||||
éventuellement des dossiers : vous avez une distribution moderne qui utilise
|
||||
la nouvelle version des `cgroup`s.
|
||||
|
||||
- Votre dossier `/sys/fs/cgroup` contient d'autres dossiers au nom des
|
||||
sous-systèmes que l'on a listé ci-dessus : il s'agit des `cgroup`s v1.
|
||||
sous-systèmes que l'on a listé ci-dessus : il s'agit des `cgroup`s v1.
|
||||
|
||||
- Votre dossier `/sys/fs/cgroup` est vide ou inexistant, vous pouvez choisir
|
||||
d'utiliser la version de votre choix :
|
||||
d'utiliser la version de votre choix :
|
||||
|
||||
Pour utiliser la v1 :
|
||||
Pour utiliser la v1 :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -70,7 +70,7 @@ l'une de ces trois situations :
|
|||
</div>
|
||||
|
||||
|
||||
Pour utiliser la v2 :
|
||||
Pour utiliser la v2 :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -103,7 +103,7 @@ La première étape dans l'utilisation d'un *cgroup* est donc de créer un group
|
|||
Pour ce faire, il suffit de créer un nouveau dossier dans un groupe existant,
|
||||
par exemple la racine.
|
||||
|
||||
On commence par se rendre à la racine :
|
||||
On commence par se rendre à la racine :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -112,7 +112,7 @@ cd /sys/fs/cgroup/ # v2
|
|||
```
|
||||
</div>
|
||||
|
||||
Puis on crée notre groupe :
|
||||
Puis on crée notre groupe :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -134,7 +134,7 @@ version, vous allez devoir activer le ou les contrôleurs dont vous avez besoin
|
|||
sous-système que l'on voulait).
|
||||
|
||||
Pour activer le contrôleur *memory* dans notre groupe `virli`, nous utilisons
|
||||
la commande suivante :
|
||||
la commande suivante :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -163,9 +163,9 @@ le fichier `cgroup.procs` de notre groupe. Ce fichier contient la liste des
|
|||
processus rattachés à notre *cgroup*.
|
||||
|
||||
Ouvrons un nouveau terminal (c'est lui que l'on va geler), et récupérons son
|
||||
PID : `echo $$`.
|
||||
PID : `echo $$`.
|
||||
|
||||
Pour ajouter une tâche à ce groupe, cela se passe de cette manière :
|
||||
Pour ajouter une tâche à ce groupe, cela se passe de cette manière :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -190,7 +190,7 @@ adaptés.
|
|||
En affichant le contenu du dossier `virli`, nous pouvions constater que
|
||||
celui-ci contenait déjà un certain nombre de fichiers. Certains d'entre-eux
|
||||
sont en lecture seule et permettent de lire des statistiques instantanées sur
|
||||
le groupe ; tandis que d'autres sont des propriétés que nous pouvons modifier.
|
||||
le groupe ; tandis que d'autres sont des propriétés que nous pouvons modifier.
|
||||
|
||||
Nous pouvons consulter l'état de gel du groupe en affichant le contenu du
|
||||
fichier\
|
||||
|
@ -204,7 +204,7 @@ consultez
|
|||
### Changement d'état
|
||||
|
||||
Faisons exécuter à notre interpréteur une commande pour voir effectivement
|
||||
l'exécution s'arrêter. Si vous manquez d'inspiration, utilisez :
|
||||
l'exécution s'arrêter. Si vous manquez d'inspiration, utilisez :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -213,7 +213,7 @@ for i in $(seq 9999); do echo -n $i; sleep .1; echo -n " - "; sleep .1; done
|
|||
</div>
|
||||
|
||||
Maintenant, nous avons donné l'ordre au noyau de ne plus allouer de temps de
|
||||
calcul à notre shell et ses fils :
|
||||
calcul à notre shell et ses fils :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -223,7 +223,7 @@ echo 1 > /sys/fs/cgroup/virli/cgroup.freeze # v2
|
|||
</div>
|
||||
|
||||
À cet instant, vous devriez voir votre compteur s'arrêter. Pour reprendre
|
||||
l'exécution :
|
||||
l'exécution :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -233,7 +233,7 @@ echo 0 > /sys/fs/cgroup/virli/cgroup.freeze # v2
|
|||
</div>
|
||||
|
||||
|
||||
### Exercice : script de monitoring {- #script-monitoring}
|
||||
### Exercice : script de monitoring {- #script-monitoring}
|
||||
|
||||
À nous maintenant de concevoir un script qui va enregistrer vers une base de
|
||||
données des statistiques issues des *cgroup*s, tel `telegraf`.
|
||||
|
@ -267,7 +267,7 @@ doit cependant être possible d'y trouver des statistiques intéressantes, dont
|
|||
la quantité de mémoire utilisée. Ici nous affichons au début le PID du
|
||||
processus, ce qui peut simplifier le débogage du script.\
|
||||
|
||||
Il s'utilise de la manière suivante :
|
||||
Il s'utilise de la manière suivante :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -275,7 +275,7 @@ Il s'utilise de la manière suivante :
|
|||
```
|
||||
</div>
|
||||
|
||||
Où :
|
||||
Où :
|
||||
|
||||
- `group_name` correspond au nom du/des *cgroup*(s) à créer/rejoindre.
|
||||
- `prog [args [...]]` est la commande que l'on souhaite monitorer, à exécuter
|
||||
|
@ -297,7 +297,7 @@ quantité de ressources mises à disposition à un groupe de processus.
|
|||
Pour définir une limite, nous allons écrire la valeur dans le fichier
|
||||
correspondant à une valeur limite, comme par exemple
|
||||
`memory.max_usage_in_bytes`/`memory.max`, qui limite le nombre d'octets que
|
||||
notre groupe de processus va pouvoir allouer au maximum :
|
||||
notre groupe de processus va pouvoir allouer au maximum :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
|
@ -330,7 +330,7 @@ limiteurs, n'hésitez pas à consulter la documentation associée à chaque
|
|||
*cgroup*.
|
||||
|
||||
Mettez à jour votre script de monitoring pour prendre en compte les
|
||||
limites que vous avez définies :
|
||||
limites que vous avez définies :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
|
@ -352,5 +352,5 @@ limites que vous avez définies :
|
|||
### Pour aller plus loin {-}
|
||||
|
||||
Pour tout connaître en détails, [la série d'articles de Neil Brown sur les
|
||||
Control groups](https://lwn.net/Articles/604609/) est excellente ! Plus [cet
|
||||
Control groups](https://lwn.net/Articles/604609/) est excellente ! Plus [cet
|
||||
article sur la version 2](https://lwn.net/Articles/679786/).
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
L'isolation ... à 1 € ?
|
||||
L'isolation ... à 1 € ?
|
||||
-----------------------
|
||||
|
||||
Depuis les premières versions d'Unix, il est possible de changer le répertoire
|
||||
|
@ -83,7 +83,7 @@ pacstrap newroot/
|
|||
</div>
|
||||
|
||||
Dans les deux cas, nous nous retrouvons avec un dossier `newroot` contenant une
|
||||
distribution complète minimale, dans laquelle nous pouvons entrer :
|
||||
distribution complète minimale, dans laquelle nous pouvons entrer :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -100,9 +100,10 @@ sous forme de tarball :
|
|||
|
||||
#### Gentoo\
|
||||
|
||||
<http://gentoo.mirrors.ovh.net/gentoo-distfiles/releases/amd64/autobuilds/current-stage3-amd64-openrc/stage3-amd64-openrc-20211128T170532Z.tar.xz>
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
wget http://gentoo.mirrors.ovh.net/gentoo-distfiles/releases/amd64/autobuilds/current-stage3-amd64/stage3-amd64-20210630T214504Z.tar.xz
|
||||
tar xpf stage3-amd64-*.tar.xz -C newroot/
|
||||
```
|
||||
</div>
|
||||
|
@ -113,7 +114,7 @@ environnement qui tient dans 200 MB.
|
|||
:::::
|
||||
|
||||
Comme pour les autres distributions vues précédemment, nous pouvons entrer dans
|
||||
notre nouvelle racine comme ceci :
|
||||
notre nouvelle racine comme ceci :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
@ -124,15 +125,16 @@ chroot newroot/ bash
|
|||
|
||||
#### Alpine\
|
||||
|
||||
<https://dl-cdn.alpinelinux.org/alpine/v3.14/releases/x86_64/alpine-minirootfs-3.14.2-x86_64.tar.gz>
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
wget https://dl-cdn.alpinelinux.org/alpine/v3.14/releases/x86_64/alpine-minirootfs-3.14.2-x86_64.tar.gz
|
||||
tar xpf alpine-minirootfs-*.tar.xz -C newroot/
|
||||
```
|
||||
</div>
|
||||
|
||||
Alpine se contentant de Busybox pour son système de base, nous n'avons pas
|
||||
`bash`, mais on peut tout de même lancer `ash` :
|
||||
`bash`, mais on peut tout de même lancer `ash` :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
|
|
|
@ -8,5 +8,5 @@ allons tâcher d'apprendre comment il fonctionne en nous penchant sur un certain
|
|||
nombre de fonctionnalités de Linux.
|
||||
|
||||
Dans un premier temps, nous allons aborder la manière dont le noyau Linux
|
||||
permet de contrôler les processus : que ce soit en collectant des informations
|
||||
permet de contrôler les processus : que ce soit en collectant des informations
|
||||
sur eux ou en imposant certaines restrictions.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Gestion de la mémoire
|
||||
=====================
|
||||
|
||||
Linux a une gestion de la mémoire bien particulière[^vm-overcommit] : par
|
||||
Linux a une gestion de la mémoire bien particulière[^vm-overcommit] : 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 blocks qu'ils ont alloués, le noyau
|
||||
|
@ -22,7 +22,7 @@ est-ce `init` qui est en train de gérer le lancement d'un nouveau daemon). On
|
|||
dit alors que le noyau est *Out-Of-Memory*.
|
||||
|
||||
Pour se sortir d'une telle situation, et après avoir tenté de vider les caches,
|
||||
il lance son arme ultime, pour retrouver au plus vite de la mémoire :
|
||||
il lance son arme ultime pour retrouver au plus vite de la mémoire :
|
||||
l'*Out-Of-Memory killer*.
|
||||
|
||||
|
||||
|
@ -39,7 +39,7 @@ jusqu'à ce que le système retrouve sa sérénité.
|
|||
[^oom-algo]: <https://linux-mm.org/OOM_Killer>
|
||||
|
||||
|
||||
## Esquiver l'OOM killer ?
|
||||
## Esquiver l'OOM killer ?
|
||||
|
||||
Au sein d'un *cgroup* *memory*, les fichiers `memory.oom_control` (v1) ou
|
||||
`memory.events` (v2) peuvent être utilisé afin de recevoir une notification du
|
||||
|
@ -58,4 +58,4 @@ ce sujet.
|
|||
Continuons l'exercice précédent où nous avions [fixé les
|
||||
limites](#Fixer-des-limites) de mémoire que pouvez réserver les processus de
|
||||
notre groupe. Que se passe-t-il alors si `memhog` dépasse la quantité de
|
||||
mémoire autorisée dans le `cgroup` ?
|
||||
mémoire autorisée dans le `cgroup` ?
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
../../subject/2/project-part1.md
|
115
tutorial/3/project-body.md
Normal file
115
tutorial/3/project-body.md
Normal file
|
@ -0,0 +1,115 @@
|
|||
## Palier 1 : Restreindre l'environnement (2 points) {-}
|
||||
|
||||
Après avoir mis en place les bases de votre programme, commencez par créer les
|
||||
différentes hiérarchies (si vous avez un noyau récent, vous pouvez utiliser les
|
||||
cgroups-v2) dont vous allez avoir besoin pour limiter l'utilisation de
|
||||
ressources.
|
||||
|
||||
Puis, mettez en place ces limites :
|
||||
|
||||
* pas plus d'1 GB de mémoire utilisée ;
|
||||
* 1 seul CPU au maximum ;
|
||||
* 100 PIDs ;
|
||||
* ...
|
||||
|
||||
En bonus, vous pouvez gérer les cas où le noyau sur lequel s'exécute votre
|
||||
moulinette ne possède pas tous ces *CGroup*s, au lieu de planter, ne rien faire
|
||||
n'est pas forcément une mauvaise solution.
|
||||
|
||||
|
||||
## Palier 2 : Réduire les `capabilities` (2 points) {-}
|
||||
|
||||
Réduisez au maximum les *capabilities*, de telle sorte qu'il ne soit pas
|
||||
possible de faire un ping dans l'environnement restreint :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
42sh# ping 9.9.9.9
|
||||
PING 9.9.9.9 (9.9.9.9) 56(84) bytes of data.
|
||||
64 bytes from 9.9.9.9: icmp_seq=1 ttl=56 time=3.93 ms
|
||||
64 bytes from 9.9.9.9: icmp_seq=2 ttl=56 time=3.97 ms
|
||||
^C
|
||||
--- 9.9.9.9 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
|
||||
rtt min/avg/max/mdev = 3.931/3.954/3.978/0.067 ms
|
||||
|
||||
42sh# ./mymoulette /bin/bash
|
||||
bash# curl http://www.linuxcontainers.org/ | md5sum
|
||||
c7d68d1cb4737125a84cd69f55add202
|
||||
|
||||
bash# ping 9.9.9.9
|
||||
ping: icmp open socket: Permission denied
|
||||
```
|
||||
</div>
|
||||
|
||||
**Astuces\ :** `prctl(2)`, `capabilities(7)`, `capget(2)`, `capset(2)`, ...
|
||||
|
||||
Aidez-vous du visualisateur de *capabilities* de la partie 1.3 du TP, pour voir
|
||||
si vous êtes sur la bonne voie.
|
||||
|
||||
Si votre distribution vous permet d'utiliser `ping` sans privilège, utilisez à
|
||||
la place n'importe quel binaire ayant besoin de *capabilities* pour vos tests,
|
||||
par exemple `arping` (qui nécessite `CAP_NET_RAW`) ou `halt` (qui nécessite
|
||||
`CAP_SYS_BOOT`) :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
42sh# ./mymoulette /bin/bash
|
||||
bash# arping 192.168.0.1
|
||||
arping: socket: Permission denied
|
||||
|
||||
bash# halt -f
|
||||
halt: (null): Operation not permitted
|
||||
```
|
||||
</div>
|
||||
|
||||
|
||||
## Palier bonus : Utilisable par un utilisateur (2 points) {-}
|
||||
|
||||
Jouez avec les attributs étendus pour qu'un utilisateur non-privilégié puisse
|
||||
exécuter votre moulinette. Ajoutez la/les commande(s) à votre `Makefile` ou
|
||||
script d'installation.
|
||||
|
||||
|
||||
## Création d'un environnement d'exécution minimal {-}
|
||||
|
||||
Plutôt que d'utiliser votre système hôte au complet, avec tous ses programmes
|
||||
et toutes ses bibliothèques, il faudrait utiliser un système contenant le
|
||||
strict minimum. Recréez un environnement minimaliste, comme on a pu en voir
|
||||
dans la partie sur les `chroot`.
|
||||
|
||||
**Ne mettez pas cet environnement dans votre tarball de rendu, il vous
|
||||
sera seulement utile pour faire des tests.**
|
||||
|
||||
|
||||
## Palier 3 : Isolation du pauvre (1 point) {-}
|
||||
|
||||
Nous n'avons pas encore vu de meilleure méthode pour mieux isoler
|
||||
l'environnement que de faire un `chroot`, ajoutez à votre programme cette
|
||||
isolation rudimentaire. Et rendez-vous au prochain cours pour avoir une
|
||||
meilleure isolation !
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
42sh$ which firefox
|
||||
/usr/bin/firefox
|
||||
42sh# ./mymoulette ./newrootfs/ /bin/bash
|
||||
bash# which firefox
|
||||
which: no firefox in (/usr/bin:/usr/local/bin:/bin:/opt/bin)
|
||||
```
|
||||
</div>
|
||||
|
||||
|
||||
## Palier 4 : seccomp (2 points) {-}
|
||||
|
||||
Filtrez les appels système de telle sorte qu'aucun programme exécuté dans
|
||||
votre bac à sable ne puisse plus lancer les appels systèmes suivants :
|
||||
|
||||
* `nfsservctl(2)` ;
|
||||
* `personality(2)` ;
|
||||
* `pivot_root(2)` ;
|
||||
* ...
|
||||
|
||||
N'hésitez pas à en utiliser d'autres pour vos tests ;)
|
||||
|
||||
**Astuces\ :** `seccomp(2)`, `seccomp_init(3)`, `seccomp_load(3)`, ...
|
|
@ -6,7 +6,7 @@ Projet et rendu
|
|||
## Sujet
|
||||
|
||||
Vous allez commencer aujourd'hui un projet qui s'étendra au prochain TP et qui
|
||||
consistera à réaliser la partie d'isolation de la moulinette des ACUs !
|
||||
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 ne puisse pas faire de déni de service sur notre machine.
|
||||
|
@ -14,11 +14,11 @@ pour qu'il ne puisse pas faire de déni de service sur notre machine.
|
|||
Il n'y a pas de restriction sur le langage utilisé, vous pouvez tout aussi bien
|
||||
utiliser du C, du C++, du Python, 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 !
|
||||
|
||||
Gardez en tête que ce projet sera à continuer au prochain TP, où il sera
|
||||
principalement question de faire des appels systèmes.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Rendu
|
||||
=====
|
||||
|
||||
Est attendu d'ici le TP suivant :
|
||||
Est attendu d'ici le TP suivant :
|
||||
|
||||
- le rendu des exercice de ce TP ;
|
||||
- vos réponses à [l'évaluation du cours](https://virli.nemunai.re/quiz/14).
|
||||
|
@ -40,7 +40,7 @@ placer dans une tarball (pas d'archive ZIP, 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">
|
||||
```
|
||||
|
|
|
@ -41,13 +41,13 @@ apporter des modifications.
|
|||
Linux emploie de nombreux systèmes de fichiers virtuels :
|
||||
|
||||
- `/proc` : contient, principalement, la liste des processus (`top` et ses
|
||||
dérivés se contentent de lire les fichiers de ce point de montage) ;
|
||||
- `/proc/sys` : contient la configuration du noyau ;
|
||||
dérivés se contentent de lire les fichiers de ce point de montage) ;
|
||||
- `/proc/sys` : contient la configuration du noyau ;
|
||||
- `/sys` : contient des informations à propos du matériel (utilisées notamment
|
||||
par `udev` pour peupler `/dev`) et des périphériques (taille des tampons,
|
||||
clignottement des DELs, ...) ;
|
||||
clignottement des DELs, ...) ;
|
||||
- `/sys/firmware/efi/efivars` : pour accéder et modifier les variables de
|
||||
l'UEFI ;
|
||||
l'UEFI ;
|
||||
- ...
|
||||
|
||||
Tous ces systèmes de fichiers sont généralement exclusivement stockés en
|
||||
|
@ -130,7 +130,7 @@ uts:[4026531838]
|
|||
Explorons le pseudo système de fichiers `/sys` pour écrire un script
|
||||
qui va, en fonction de ce que vous avez de disponible :
|
||||
|
||||
* afficher des statistiques sur notre batterie ;
|
||||
* afficher des statistiques sur notre batterie ;
|
||||
* afficher des statistiques la fréquence du CPU.
|
||||
|
||||
##### `batinfo.sh`\
|
||||
|
@ -194,7 +194,7 @@ Maintenant que vous savez lire des informations dans `/sys`, tentons d'aller
|
|||
modifier le comportement de notre système. Au choix, réalisez l'un des scripts
|
||||
suivants, en fonction du matériel dont vous disposez :
|
||||
|
||||
* inverser l'état des diodes de notre clavier ;
|
||||
* inverser l'état des diodes de notre clavier ;
|
||||
* mettre en veille votre machine, en ayant programmé une heure de réveil.
|
||||
|
||||
##### `rev_kdb_leds.sh`\
|
||||
|
@ -203,7 +203,7 @@ Si vous avez :
|
|||
|
||||
* numlock On,
|
||||
* capslock Off,
|
||||
* scrolllock Off ;
|
||||
* scrolllock Off ;
|
||||
|
||||
Après avoir exécuté le script, nous devrions avoir :
|
||||
|
||||
|
@ -242,7 +242,8 @@ Voici un exemple d'utilisation :
|
|||
</div>
|
||||
|
||||
Vous aurez besoin de définir une alarme au niveau de votre RTC, via le
|
||||
fichier : `/sys/class/rtc/rtcX/wakealarm`.
|
||||
fichier :\
|
||||
`/sys/class/rtc/rtcX/wakealarm`
|
||||
|
||||
::::: {.warning}
|
||||
Attention au fuseau horaire utilisé par votre RTC, si votre système principal
|
||||
|
|
|
@ -12,13 +12,13 @@ particulier peut être renvoyé au programme.
|
|||
Depuis la version 3.17 du noyau, l'appel système `seccomp(2)` permet de faire
|
||||
entrer le processus courant dans ce mode. En effet, c'est le processus lui-même
|
||||
qui déclare au noyau qu'il peut désormais se contenter d'une liste réduite
|
||||
d'appels système ; à l'inverse des politiques de sécurité comme SELinux ou
|
||||
d'appels système ; à l'inverse des politiques de sécurité comme SELinux ou
|
||||
AppArmor, qui encapsulent les programmes pour toute la durée de leur exécution.
|
||||
|
||||
*Seccomp* est particulièrement utile lorsqu'un processus a terminé son
|
||||
initialisation (ne dépendant en général pas de données sujettes à
|
||||
l'exploitation de vulnérabilité) et doit commencer à entrer dans des portions
|
||||
de code promptes aux vulnérabilités : c'est notamment le cas des moteurs de
|
||||
de code promptes aux vulnérabilités : c'est notamment le cas des moteurs de
|
||||
rendus des navigateurs Firefox et Chrome.
|
||||
|
||||
|
||||
|
@ -39,7 +39,7 @@ des appels système `read(2)`, `write(2)` (sur les descripteurs de fichier déj
|
|||
ouvert), `_exit(2)` et `sigreturn(2)`.
|
||||
|
||||
Historiquement, avant la création de l'appel système `seccomp(2)`, on activait
|
||||
ce mode via :
|
||||
ce mode via :
|
||||
|
||||
<div lang="en-US">
|
||||
```c
|
||||
|
@ -63,7 +63,7 @@ auquel est appliqué un filtre `seccomp`, héritent également de ce filtre.
|
|||
|
||||
La construction de ce filtre est faite de manière programmatique, via
|
||||
des règles BPF (`Berkeley Packet Filter`). On passe ensuite ce filtre BPF en
|
||||
argument de l'appel système :
|
||||
argument de l'appel système :
|
||||
|
||||
<div lang="en-US">
|
||||
```c
|
||||
|
@ -79,7 +79,7 @@ seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog);
|
|||
|
||||
### Exercice {-}
|
||||
|
||||
Écrivez un programme filtrant un appel système, à l'aide de `seccomp` :
|
||||
Écrivez un programme filtrant un appel système, à l'aide de `seccomp` :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue