Tuto 3 done

This commit is contained in:
nemunaire 2021-10-05 17:23:09 +02:00
parent 15236db9af
commit 8c402e6d65
15 changed files with 606 additions and 312 deletions

Binary file not shown.

View File

@ -1,6 +1,11 @@
include ../pandoc-opts.mk
SOURCES = tutorial.md installation.md chroot.md pseudofs.md capabilities.md cgroups.md oom.md seccomp.md project-intro.md project-body.md project-rendu.md
SOURCES = tutorial.md \
intro.md installation.md pseudofs.md capabilities.md cgroups.md cgroups-influx.md \
oom.md \
seccomp.md \
chroot-intro.md chroot.md chroot-ex-escape.md \
project-rendu.md
all: tutorial.pdf

View File

@ -1,16 +1,14 @@
\newpage
Les *capabilities*
==================
## Présentation
------------------
Historiquement, dans la tradition UNIX, on distinguait deux catégories de
processus :
processus :
* les processus *privilégiés* : dont l'identifiant numérique de son utilisateur
est 0 ;
* les processus *non-privilégiés* : dont l'identifiant numérique de son
* les processus *privilégiés* : dont l'identifiant numérique de son utilisateur
est 0 ;
* les processus *non-privilégiés* : dont l'identifiant numérique de son
utilisateur n'est pas 0.
Lors des différents tests de permission fait par le noyau, les processus
@ -21,24 +19,25 @@ Depuis Linux 2.2 (en 1998), les processus privilégiés peuvent activer ou
désactiver des *capabilities*, chacune donnant accès à un groupe d'actions
privilégiées au sein du noyau.
On trouve par exemple :
On trouve par exemple :
* `CAP_CHOWN` : permet de modifier le propriétaire d'un fichier de manière
arbitraire ;
* `CAP_KILL` : permet de tuer n'importe quel processus ;
* `CAP_SYS_BOOT` : permet d'arrêter ou de redémarrer la machine ;
* `CAP_SYS_MODULE` : permet de charger et décharger des modules ;
* et beaucoup d'autres, il y en a environ 39 en tout (ça dépend de la
version du noyau) !
* `CAP_CHOWN` : permet de modifier le propriétaire d'un fichier de manière
arbitraire ;
* `CAP_KILL` : permet de tuer n'importe quel processus ;
* `CAP_SYS_BOOT` : permet d'arrêter ou de redémarrer la machine ;
* `CAP_SYS_MODULE` : permet de charger et décharger des modules ;
* et beaucoup d'autres, il y en a environ 41 en tout (ça dépend de la
version du noyau) !
### `ping`
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'existe pas d'interface
exposée par le noyau aux utilisateurs pour envoyer des paquets ICMP. Pour le
faire, il est nécessaire de pouvoir écrire directement sur l'interface ; ça,
seul le super-utilisateur peut le faire.
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
super-utilisateur, soit que le noyau ait été configuré pour autoriser certains
utilisateurs à envoyer des `ECHO_REQUEST`.
Pour permettre à tous les utilisateurs de pouvoir envoyer des ping, le
programme est donc généralement *Setuid root*. Cela permet à n'importe quel
@ -48,35 +47,88 @@ du programme.
Les problèmes surviennent lorsque l'on découvre des vulnérabilités dans les
programmes *Setuid root*. En effet, s'il devient possible pour un utilisateur
d'exécuter du code arbitraire, ce code sera exécuté avec les privilèges de
l'utilisateur *root* ! Dans le cas de `ping`, on se retrouverait alors à
l'utilisateur *root* ! Dans le cas de `ping`, on se retrouverait alors à
pouvoir lire l'intégralité de la mémoire, alors que l'on avait juste besoin
d'écrire sur une interface réseau.
C'est donc à ce moment que les *capabilities* entrent en jeu : un processus (ou
C'est donc à ce moment que les *capabilities* entrent en jeu : un processus (ou
même un thread) privilégié peut décider, généralement à son lancement, de
réduire ses *capabilities*, pour ne garder que celles dont il a réellement
besoin. Ainsi, `ping` pourrait se contenter de `CAP_NET_RAW`.
::::: {.warning}
Bien que ce paramètre existe [depuis
2011](https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=c319b4d76b9e583a5d88d6bf190e079c4e43213d),
ce n'est que [depuis 2020](https://github.com/systemd/systemd/pull/13141) que les distributions comme Fedora et Ubuntu
se mettent à fournir par défaut une configuration qui permette de se passer de
*capabilities* pour lancer `ping`.\
## Les attributs de fichier étendus
Si vous vous rendez compte que votre binaire `ping` est dans ce cas, testez
depuis un conteneur, par exemple :
Une grosse majorité des systèmes de fichiers (ext[234], XFS, btrfs, ...)
<div lang="en-US">
```
42sh$ docker run -it --rm alpine
(ctnr)# apk add --no-cache acl iputils
(1/4) Installing libacl (2.2.53-r0)
(2/4) Installing acl (2.2.53-r0)
(3/4) Installing libcap (2.50-r0)
(4/4) Installing iputils (20210202-r0)
(ctnr)# su -s/bin/ash daemon
(ctnr)$ _
```
</div>
Dans le conteneur le binaire `ping` est *setuid root*, vous pouvez faire des
tests en retirant le *setuid* :
<div lang="en-US">
```
(ctnr)# chmod u-s /bin/ping
(ctnr)$ ping epita.fr
ping: socket: Operation not permitted
```
</div>
Puis en ajoutant la *capability* :
<div lang="en-US">
```
(ctnr)# setcap cap_net_raw+p /bin/ping
(ctnr)$ ping epita.fr
PING epita.fr (172.67.156.141) 56(84) bytes of data.
```
</div>
Vous vous retrouverez dans le scénario attendu, tout en pouvant agir sur le
binaire `ping` sans avoir peur de casser votre distribution.
:::::
### Les attributs de fichier étendus
Une grosse majorité des systèmes de fichiers (ext[234], XFS, btrfs, ...)
permet d'enregistrer, pour chaque fichier, des attributs (dits attributs
*étendus*, par opposition aux attributs *réguliers* qui sont réservés à l'usage
du système de fichiers).
Sous Linux, les attributs sont regroupés dans des espaces de noms :
Sous Linux, les attributs sont regroupés dans des espaces de noms :
* *security* : espace utilisé par les modules de sécurité du noyau, tel que
SELinux, ... ;
* *system* : espace utilisé par le noyau pour stocker des objets système, tels
que les ACL POSIX ;
* *security* : espace utilisé par les modules de sécurité du noyau, tel que
SELinux, ... ;
* *system* : espace utilisé par le noyau pour stocker des objets système, tels
que les ACL POSIX ;
* *trusted*: espace dont la lecture et l'écriture est limité au
super-utilisateur ;
* *user* : modifiable sans restriction, à partir du moment où l'on est le
super-utilisateur ;
* *user* : modifiable sans restriction, à partir du moment où l'on est le
propriétaire du fichier.
Par exemple, on peut définir un attribut sur un fichier comme cela :
Par exemple, on peut définir un attribut sur un fichier comme cela :
<div lang="en-US">
```bash
@ -88,14 +140,16 @@ user.foo="bar"
```
</div>
Encore plus fort, vous pouvez utiliser les ACL POSIX :
En tant que simple utilisateur, vous ne pouvez pas modifier des attributs en
dehors de l'espace *user*. Par contre, en *root*, vous pouvez définir et
changer les ACL POSIX :
<div lang="en-US">
```bash
42sh$ sudo chown root:root toto && sudo chmod o-r toto
42sh$ cat toto
cat: toto: Permission denied
42sh$ sudo setfattr -m u:$USER:r toto
42sh$ sudo setfacl -m u:$USER:r toto
42sh$ cat toto
Hello World!
```
@ -104,7 +158,7 @@ Hello World!
Bien que les droits UNIX traditionnels ne vous donnent pas accès au fichier,
les ACL POSIX vous autorisent à le lire.
Vous pouvez voir ces attributs avec la commande :
Vous pouvez voir ces attributs bruts avec la commande :
<div lang="en-US">
```bash
@ -114,17 +168,19 @@ system.posix_acl_access=0sgAAEAD/////AgAEOgDAEAA/////xAABAD////8=
```
</div>
Il s'agit d'une représentation d'une structure du noyau, pas forcément très
lisible en l'état. On utilisera `getfacl` pour la version lisible.
### `ping`
#### `ping`\
De la même manière que l'on peut définir de façon plus fine les droits d'accès
par utilisateur, un attribut de l'espace de nom *security* peut être défini
pour accroître les *capabilities* d'un processus lorsqu'il est lancé par un
utilisateur non-privilégié. On peut alors voir le Setuid root comme
l'utilisation de cet attribut auquel on accroîtrait l'ensemble des
*capabilities*.
utilisateur non-privilégié. On peut voir le *setuid root* comme l'utilisation
de cet attribut, qui accroîtrait l'ensemble des *capabilities*.
Si votre distribution profite de ces attributs étendus, vous devriez obtenir :
Si votre distribution profite de ces attributs étendus, vous devriez obtenir :
<div lang="en-US">
```bash
@ -134,7 +190,8 @@ security.capability=0sAQAAAgAgAAAAAAAAAAAAAAAAAAA=
```
</div>
Ou, dans sa version plus lisible :
Comme pour les ACL POSIX, une structure du noyau est enregistrée comme attribut
du fichier ; et on peut l'afficher dans sa version plus lisible :
<div lang="en-US">
```bash
@ -144,10 +201,10 @@ Ou, dans sa version plus lisible :
</div>
## Exercice : visualisateur de capabilities d'un processus {-}
### Exercice : visualisateur de capabilities d'un processus {-}
Écrivons maintenant un programme permettant de voir les *capabilities*
d'un processus :
d'un processus :
<div lang="en-US">
```
@ -179,24 +236,27 @@ inheritable: 0x0
```
</div>
Astuces : `capget(2)`, X-macros, ...
Appelé sans argument, `view_caps` affichera les capabilities du processus
courant.
Astuces : `capget(2)`, X-macros, ...
## Pour aller plus loin {-}
### Pour aller plus loin {-}
Je vous recommande la lecture des *man* suivants :
Je vous recommande la lecture des *man* suivants :
* `capabilities(7)` : énumérant tous les capabilities, leur utilisation, etc. ;
* `xattrs(7)` : à propos des attributs étendus.
* `capabilities(7)` : énumérant tous les capabilities, leur utilisation, etc. ;
* `xattrs(7)` : à propos des attributs étendus.
Et de ces quelques articles :
Et de ces quelques articles :
* [Secure Your Containers with this One Weird Trick](https://www.redhat.com/en/blog/secure-your-containers-one-weird-trick)
* [Linux Capabilities: Why They Exist and How They Work](https://blog.container-solutions.com/linux-capabilities-why-they-exist-and-how-they-work)
* [Guidelines for extended attributes](https://www.freedesktop.org/wiki/CommonExtendedAttributes/)
* [File-based capabilities](https://lwn.net/Articles/211883/)
* [A bid to resurrect Linux capabilities](https://lwn.net/Articles/199004/)
* [False Boundaries and Arbitrary Code Execution](https://forums.grsecurity.net/viewtopic.php?f=7&t=2522#p10271)
Pour revenir à Docker, par défaut, un certain nombre de *capabilities* sont
sactivées par défaut ; vous pouvez en ajouter et en retirer via les arguments
`--cap-add` et `--cap-drop` du `docker container run`.
Pour revenir à Docker, un certain nombre de *capabilities* sont désactivées par
faut ; vous pouvez en ajouter et en retirer via les arguments `--cap-add` et
`--cap-drop` du `docker container run`.

View File

@ -0,0 +1,87 @@
### 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`
#### Rappel d'InfluxDB\
Commençons par lancer le conteneur Docker d'InfluxDB (pour éviter de
l'installer sur notre machine) :
<div lang="en-US">
```bash
docker container run --name mytsdb -d -p 8086:8086 influxdb:1.8
```
</div>
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 :
<div lang="en-US">
```bash
docker container exec -i mytsdb influx <<EOF
CREATE DATABASE metrics;
SHOW DATABASES;
EOF
```
</div>
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/> :
<div lang="en-US">
```bash
curl -i -XPOST 'http://localhost:8086/write?db=metrics' --data-binary \
"$my_cgroup_name memory.usage_in_bytes=$(cat .../my_cgroup_name/memory.usage_in_bytes)"
```
</div>
Pour vérifier que les données ont bien été ajoutées, nous pouvons effectuer la
requête suivante dans notre client `influx` :
<div lang="en-US">
```sql
SELECT * from "$my_cgroup_name";
```
</div>
#### Monitorer davantage de données\
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) ;
* ...
Tous les cgroups existants dans le dernier noyau publié ont leur documentation
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>
#### Permettre à l'utilisateur de monitorer des processus\
Maintenant, séparons notre script en deux parties afin qu'un utilisateur normal
(non-root) puisse utiliser la partie monitoring de notre script.
Un premier script doit s'occuper de créer le(s) *cgroup*s et lui attribuer les
bons droits, tandis que le deuxième va effectuer le monitoring, sans privilèges
particuliers.
##### Exemple {-}
<div lang="en-US">
```
42sh$ sudo ./telegraf_init.sh my_cgroup_name
42sh$ ./telegraf.sh my_cgroup_name memhog 500
```
</div>

View File

@ -1,50 +1,123 @@
\newpage
Utiliser les *cgroup*s
======================
Les *cgroup*s
-------------
Les *cgroup*s (pour *Control Group*s) permettent de collecter des statistiques
sur des groupes de processus (appelés tâches) et de leur attribuer des
propriétés. Par exemple, il est possible leur imposer des limites d'utilisation
de ressources ou d'altérer leur comportement.
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é
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
(*subsystem*), chacun étant responsable d'un type de ressources
spécifique :
## Premiers tests
- [`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 ;
- [`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é ;
- [`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) ;
- [`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 ;
- [`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 ;
- ...
Nous allons commencer par faire quelques tests avec le *cgroup* *freezer*, qui
permet d'interrompre l'exécution d'un groupe de processus et de la reprendre.
permet d'interrompre l'exécution d'un groupe de processus, puis de la reprendre
lorsqu'on le décide.
### Montage du *cgroup*
### Montage du *freezer*
En fonction de la configuration de votre système, il est possible que les
*cgroup*s ne soient pas montés au démarrage dans `/sys/fs/cgroup/`. Si vous n'avez
pas de dossier `freezer` ou si celui-ci est vide, montez-le en suivant la
procédure suivante :
En fonction de la configuration de votre système, vous allez vous trouver dans
l'une de ces trois situations :
<div lang="en-US">
```bash
mkdir /sys/fs/cgroup/freezer/
mount -t cgroup -o freezer none /sys/fs/cgroup/freezer/
```
</div>
- Votre dossier `/sys/fs/cgroup` contient à la fois des fichiers `cgroup.*` et
éventuellement des dossiers : vous avez une distribution moderne qui utilise
la nouvelle version des `cgroup`s.
Cette dernière commande monte l'arborescence de groupes relative à ce *cgroup*
*freezer*. Tous les dossiers contenus dans cette racine sont donc des
sous-groupes.
- 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.
- Votre dossier `/sys/fs/cgroup` est vide ou inexistant, vous pouvez choisir
d'utiliser la version de votre choix :
Pour utiliser la v1 :
<div lang="en-US">
```bash
mkdir /sys/fs/cgroup/freezer/
mount -t cgroup -o freezer none /sys/fs/cgroup/freezer/
```
</div>
Pour utiliser la v2 :
<div lang="en-US">
```bash
mkdir /sys/fs/cgroup/
mount -t cgroup2 none /sys/fs/cgroup/
```
</div>
::::: {.question}
Avant d'aller plus loin, notez que les exemples seront donnés pour les deux
versions des `cgroup`s à chaque fois.
La principale différence entre les deux est la fusion des différents
sous-systèmes au sein d'une même arborescence. Dans la première version, chaque
sous-système disposait de sa propre arborescence et il fallait créer les
groupes et associer les tâches pour chaque sous-système. Avec la seconde
version, une seule création est nécessaire, quelque soit le nombre de
sous-systèmes que l'on souhaite utiliser.
:::::
### Création d'un nouveau groupe
La première étape dans l'utilisation d'un *cgroup* est de créer un groupe.
Les *cgroup*s sont organisé autour d'une arborescence de groupe, où chaque
groupe est représenté par un dossier. Il peut bien évidemment y avoir des
sous-groupes, en créant des dossiers dans les dossiers existants, etc.\
La première étape dans l'utilisation d'un *cgroup* est donc de créer un groupe.
Pour ce faire, il suffit de créer un nouveau dossier dans un groupe existant,
par exemple la racine :
par exemple la racine.
On commence par se rendre à la racine :
<div lang="en-US">
```bash
mkdir /sys/fs/cgroup/freezer/virli/
ls /sys/fs/cgroup/freezer/virli/
cd /sys/fs/cgroup/freezer/ # v1
cd /sys/fs/cgroup/ # v2
```
</div>
Puis on crée notre groupe :
<div lang="en-US">
```bash
mkdir virli
ls virli/
```
</div>
@ -53,19 +126,50 @@ Nous avons maintenant un nouveau groupe de processus `virli` dans le *cgroup*
propriétés de son (ses) père(s).
### Sélection de contrôleur (v2 seulement)
Du fait de l'unification de tous les sous-systèmes, si vous utilisez la seconde
version, vous allez devoir activer le ou les contrôleurs dont vous avez besoin
(tandis que dans la première version, on se rendait dans l'arborescence du
sous-système que l'on voulait).
Pour activer le contrôleur *memory* dans notre groupe `virli`, nous utilisons
la commande suivante :
<div lang="en-US">
```bash
echo "+memory" > virli/cgroup.subtree_control
```
</div>
::::: {.warning}
Si vous obtenez l'erreur `No such file or directory`, c'est sans doute que vous
avez les `cgroup`s v1 activé quelque part. Vous devriez plutôt utiliser la
première version, le fait qu'elle soit active empêche l'utilisation de la v2 en
parallèle.
:::::
On peut contrôler les contrôleurs actifs en consultant le fichier
`virli/cgroup.controllers`.
Le contrôleur *freezer* est activé par défaut, il n'y a pas besoin de
l'activer.
### Rattachement de processus
Pour le moment, ce nouveau groupe ne contient aucune tâche.
Pour le moment, ce nouveau groupe ne contient aucun processus, comme le montre
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 $$`.
La liste des processus rattachés à un *cgroup* se trouve dans le fichier `task`
du groupe. 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
echo $PID > /sys/fs/cgroup/freezer/virli/tasks
echo $PID > /sys/fs/cgroup/{,freezer/}virli/cgroup.procs
```
</div>
@ -75,7 +179,7 @@ En validant cette commande, nous avons déplacé le processus dans ce groupe, il
n'est alors plus dans aucun autre groupe (pour ce *cgroup*, il ne bouge pas
dans les autres *cgroup*s).
Malgré l'utilisation de la redirection `>` (et non `>>`), il s'agit belle et
Malgré l'utilisation de la redirection `>` (et non `>>`), il s'agit bel et
bien d'un ajout au fichier et non d'un écrasement. Il faut garder en tête que
le système de fichier est entièrement simulé et que certains comportements sont
adaptés.
@ -84,15 +188,15 @@ adaptés.
### Consultation de l'état
En affichant le contenu du dossier `virli`, nous pouvions constater que
celui-ci contenait déjà un certain nombre de fichiers. Certain 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.
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.
Nous pouvons consulter l'état de gel du groupe en affichant le contenu du
fichier\
`/sys/fs/cgroup/freezer/virli/freezer.state`.
`/sys/fs/cgroup/freezer/virli/freezer.state` ou `/sys/fs/cgroup/virli/cgroup.freeze`.
Pour plus d'information sur les différents fichiers présents dans ce *cgroup*,
Pour plus d'informations sur les différents fichiers présents dans ce *cgroup*,
consultez
[la documentation associée](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/freezer-subsystem.html).
@ -113,7 +217,8 @@ calcul à notre shell et ses fils :
<div lang="en-US">
```bash
echo FROZEN > /sys/fs/cgroup/freezer/virli/freezer.state
echo FROZEN > /sys/fs/cgroup/freezer/virli/freezer.state # v1
echo 1 > /sys/fs/cgroup/virli/cgroup.freeze # v2
```
</div>
@ -122,57 +227,30 @@ l'exécution :
<div lang="en-US">
```bash
echo THAWED > /sys/fs/cgroup/freezer/virli/freezer.state
echo THAWED > /sys/fs/cgroup/freezer/virli/freezer.state # v1
echo 0 > /sys/fs/cgroup/virli/cgroup.freeze # v2
```
</div>
## Exercice : script de 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.
### Rappel d'InfluxDB
Commençons par lancer le conteneur Docker d'InfluxDB (pour éviter de
l'installer sur notre machine) :
<div lang="en-US">
```bash
docker container run --name mytsdb -d -p 8086:8086 influxdb
```
</div>
Il nous faut ensuite créer une base de données pour y stocker nos
métriques. Voici comment on s'était débrouillé dans un précédent TP pour
interagir avec InfluxDB :
<div lang="en-US">
```bash
docker container exec -i mytsdb influx <<EOF
CREATE DATABASE metrics;
SHOW DATABASES;
EOF
```
</div>
Vérifiez que la base de données `metrics` a bien été créée.
### Monitoring instantané vers la console
données des statistiques issues des *cgroup*s, tel `telegraf`.
Dans un premier temps, commençons par afficher dans la console, la quantité de
mémoire utilisée par le groupe monitoré.
::::: {.code}
Vous pouvez utiliser un programme comme
[`memhog`](https://virli.nemunai.re/memhog.c) pour remplir rapidement votre
mémoire.
:::::
<div lang="en-US">
```
42sh# mkdir /sys/fs/cgroup...
42sh$ echo $$ | sudo tee /sys/fs/cgroup.../tasks
42sh$ echo $$ | sudo tee /sys/fs/cgroup.../cgroup.procs
42sh# ./monitor group_name memhog 500
~~~ 13595 ~~~ Current memory usage: 75194368/550502400 (13%)
~~~ 13595 ~~~ Current memory usage: 150290432/550502400 (27%)
@ -185,79 +263,26 @@ mémoire.
```
</div>
::::: {.warning}
Si vous n'avez pas le *cgroup* *memory*, il est possible qu'il ne soit pas
activé par défaut par votre système. Si vous êtes dans ce cas, essayez
d'ajouter `cgroup_enable=memory` à la ligne de commande de votre noyau.
:::::
### Monitoring vers InfluxDB
### Fixer des limites {#Fixer-des-limites}
Maintenant, envoyons nos données vers la base
<https://docs.influxdata.com/influxdb/v1.6/guides/writing_data/> :
<div lang="en-US">
```bash
curl -i -XPOST 'http://localhost:8086/write?db=metrics' --data-binary \
"$my_cgroup_name memory.usage_in_bytes=$(cat .../my_cgroup_name/memory.usage_in_bytes)"
```
</div>
Pour vérifier que les données ont bien été ajoutées, nous pouvons effectuer la
requête suivante dans notre client `influx` :
<div lang="en-US">
```sql
SELECT * from "$my_cgroup_name";
```
</div>
### Monitorer davantage de données
Liste non exhaustive de données à monitorer :
* Nombre d'IOs effectué ;
* nombre d'octets lu/écrit sur les disques ;
* temps de calcul utilisé ;
* trafic réseau généré ;
* ...
Tous les cgroups existants dans le dernier noyau publié ont leur documentation
accessible ici :
<https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/index.html>
### Permettre à l'utilisateur de monitorer des processus
Maintenant, séparons notre script en deux parties afin qu'un utilisateur normal
(non-root) puisse utiliser la partie monitoring de notre script.
Un premier script doit s'occuper de créer le(s) *cgroup*s et lui attribuer les
bons droits, tandis que le deuxième va effectuer le monitoring, sans privilèges
particuliers.
#### Exemple
<div lang="en-US">
```
42sh$ sudo ./monitor_init my_cgroup_name
42sh$ ./monitor my_cgroup_name memhog 500
```
</div>
## Fixer des limites
Au delà de la simple consultation, les *cgroup*s peuvent servir à limiter la
quantité de ressources mise à disposition à un groupe de processus.
Au-delà de la simple consultation, les *cgroup*s peuvent servir à limiter la
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`, qui limite le nombre d'octets que notre groupe de
processus va pouvoir allouer au maximum :
`memory.max_usage_in_bytes`/`memory.max`, qui limite le nombre d'octets que
notre groupe de processus va pouvoir allouer au maximum :
<div lang="en-US">
```
# cgroup v1
42sh$ cat /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes
0
# 0 = Aucune limite
@ -268,21 +293,26 @@ processus va pouvoir allouer au maximum :
```
</div>
Chaque *cgroup*s défini de nombreux indicateurs et possède de nombreux
<div lang="en-US">
```
# cgroup v2
42sh$ cat /sys/fs/cgroup/virli/memory.max
max
# max = Aucune limite
42sh$ echo 4M > /sys/fs/cgroup/virli/memory.max
# Maintenant, la limite est à 4MB, vérifions...
42sh$ cat /sys/fs/cgroup/virli/memory.max
4194304
```
</div>
Chaque *cgroup*s définit de nombreux indicateurs et possède de nombreux
limiteurs, n'hésitez pas à consulter la documentation associée à chaque
*cgroup*.
## Pour aller plus loin {-}
### 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 !
Depuis les noyaux 4.5, il est possible d'utiliser la nouvelle version du
pseudo système de fichiers des *CGroup*s. Le principal changement vient du
regroupement au sein d'une seule hiérarchie des différents *CGroup*s que l'on
avait dans la v1. Davantage d'informations sont disponibles :
* [Understanding the new control groups API](https://lwn.net/Articles/679786/)
;
* [Kernel Document about Control Group v2](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html).
Control groups](https://lwn.net/Articles/604609/) est excellente ! Plus [cet
article sur la version 2](https://lwn.net/Articles/679786/).

View File

@ -0,0 +1,28 @@
## Exercice (SRS seulement) {-}
Écrivons maintenant un programme dont le seul but est de s'échapper du `chroot` :
<div lang="en-US">
```bash
make escape
echo bar > ../foo
chroot .
```
</div>
Dans le nouvel environnement, vous ne devriez pas pouvoir faire :
<div lang="en-US">
```bash
cat ../foo
```
</div>
Mais une fois votre programme `escape` exécuté, vous devriez pouvoir !
<div lang="en-US">
```
(chroot) 42sh# ./escape
bash# cat /path/to/foo
```
</div>

View File

@ -0,0 +1,12 @@
\newpage
En route vers la contenerisation
================================
Nous avons vu un certain nombre de fonctionnalités offertes par le noyau Linux
pour limiter ou autoriser ou contraindre différents usages des ressources de
notre machine.
Il est temps maintenant de commencer à parler d'isolation, mais ... cela fait
déjà beaucoup à digérer pour aujourd'hui, alors on va se contenter de parler
d'un mécanisme que vous connaissez sans doute déjà.

View File

@ -1,18 +1,15 @@
\newpage
L'isolation ... du pauvre
=========================
L'isolation ... à 1 € ?
-----------------------
Depuis les premières versions d'Unix, il est possible de changer le répertoire
vu comme étant la racine du système de fichiers. En anglais : *change root*:
`chroot`. Le processus effectuant cette action ainsi que tous ses fils, verront
donc une racine différente du reste du système.
vu comme étant la racine du système de fichiers. En anglais : *change root*:
`chroot`. Le processus effectuant cette action ainsi que tous ses fils verront
donc une racine différente du reste du système.\
## Mise en place de l'environnement
Pour se créer un environnement afin de changer notre racine, il va falloir
commencer par créer le dossier de notre nouvelle racine :
commencer par créer le dossier de notre nouvelle racine, peu importe où dans
l'arborescence :
<div lang="en-US">
```bash
@ -20,13 +17,21 @@ mkdir newroot
```
</div>
Nous allons ensuite remplir ce dossier afin qu'il soit vraiment utilisable
comme une racine : rien n'est strictement obligatoire, on s'assure simplement
d'avoir de quoi bidouiller : un shell sera amplement suffisant pour commencer.
### `busybox`
Queques mots, pour commencer, à propos du projet Busybox : c'est un programme
*linké* statiquement, c'est-à-dire qu'il ne va pas chercher ni charger de
bibliothèque dynamique à son lancement. Il se suffit donc à lui-même dans un
*chroot*, car il n'a pas de dépendances. Nous pouvons donc tester notre
première isolation\ :
Queques mots, pour commencer, à propos du projet Busybox : c'est un programme
couteau-suisse qui implémente tous les binaires vitaux pour avoir un système
fonctionnel et utilisable : `ls`, `sh`, `cat`, mais aussi `init`, `mdev` (un
`udev`-like, cela permet de découvrir les périphériques attachés afin de les
exposer dans `/dev` notamment). C'est un programme *linké* statiquement,
c'est-à-dire qu'il ne va pas chercher ni charger de bibliothèque dynamique à
son lancement. Il se suffit donc à lui-même dans un *chroot*, car il n'a pas de
dépendances. Nous pouvons donc tester notre première isolation :
<div lang="en-US">
```bash
@ -35,8 +40,11 @@ chroot newroot /busybox ash
```
</div>
Jusque là ... ça fonctionne, rien de surprenant ! Mais qu'en est-il pour
`bash` :
Nous voici donc maintenant dans un nouveau shell (il s'agit d'`ash`, le shell
de `busybox`).
Jusque là ... ça fonctionne, rien de surprenant ! Mais qu'en est-il pour
`bash` :
<div lang="en-US">
```bash
@ -46,10 +54,10 @@ chroot: failed to run command bash: No such file or directory
```
</div>
De quel fichier est-il question ici ?
De quel fichier est-il question ici ?
### `debootstrap`
### `debootstrap`, `pacstrap`
`debootstrap` est le programme utilisé par l'installeur des distributions
Debian et ses dérivées. Il permet d'installer dans un dossier (en général, ce
@ -58,54 +66,76 @@ l'utilisateur lors de l'installation) le système de base.
<div lang="en-US">
```bash
debootstrap buster newroot/ http://httpredir.debian.org/debian/
debootstrap bullseye newroot/ http://httpredir.debian.org/debian/
```
</div>
`pacstrap` est le programme équivalent pour Archlinux.
### *stage3*
Les distributions *à l'ancienne* proposent encore de télécharger leur système
de base sous forme de tarball\ :
`pacstrap` est le programme équivalent pour Arch Linux. Alors que `debootstrap`
peut s'utiliser depuis n'importe quel environnement ou distribution,
`pacstrap` nécessite d'avoir installé et configuré `pacman` (le gestionnaire de
paquets d'Arch Linux), ce qui est le cas si vous êtes sous Arch Linux ou ses
dérivées.
<div lang="en-US">
```bash
wget http://gentoo.mirrors.ovh.net/gentoo-distfiles/releases/amd64/autobuilds/current-stage3-amd64/stage3-amd64-20201104T214503Z.tar.xz
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 :
<div lang="en-US">
```bash
chroot newroot/ bash
```
</div>
### Archives *stage3*, *miniroot*
Les distributions *à l'ancienne* proposent de télécharger leur système de base
sous forme de tarball :
#### Gentoo\
<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>
::::: {.more}
L'avantage de télécharger l'archive de Gentoo est que l'on a déjà `gcc` dans un
environnement qui tient dans 300 MB.
environnement qui tient dans 200 MB.
:::::
## Exercice {-}
Écrivons maintenant un programme dont le seul but est de s'échapper du `chroot` :
Comme pour les autres distributions vues précédemment, nous pouvons entrer dans
notre nouvelle racine comme ceci :
<div lang="en-US">
```bash
make escape
echo bar > ../foo
chroot .
chroot newroot/ bash
```
</div>
Dans le nouvel environnement, vous ne devriez pas pouvoir faire :
#### Alpine\
<div lang="en-US">
```bash
cat ../foo
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>
Mais une fois votre programme `escape` exécuté, vous devriez pouvoir !
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` :
<div lang="en-US">
```
(chroot) 42sh# ./escape
bash# cat /path/to/foo
```bash
chroot newroot/ ash
```
</div>

View File

@ -1,13 +1,12 @@
\newpage
Prérequis
=========
---------
## Noyau Linux
### Noyau Linux
Ce TP requiert un noyau Linux, dans sa version 3.8 au minimum. Il doit de plus
être compilé avec les options suivantes (lorsqu'elles sont disponibles pour
votre version) :
Pour pouvoir suivre les exemples et faire les exercices qui suivent, vous aurez
besoin d'un noyau Linux récent (une version 5.x sera très bien). Il doit de
plus être compilé avec les options suivantes (lorsqu'elles sont disponibles
pour votre version) :
<div lang="en-US">
```
@ -31,7 +30,7 @@ General setup --->
</div>
### Vérification via `menuconfig`
#### Vérification via `menuconfig`\
L'arbre ci-dessous correspond aux options qui seront *built-in* (signalées par
une `*`) ou installées en tant que module (signalées par un `M`). En effet,
@ -42,7 +41,7 @@ Pour parcourir l'arbre des options du noyau, il est nécessaire d'avoir les
sources de celui-ci. Les dernières versions stables et encore maintenues sont
disponibles sur la page d'accueil de <https://kernel.org>.
Dans les sources, on affiche la liste des options avec la commande :
Dans les sources, on affiche la liste des options avec la commande :
<div lang="en-US">
```bash
@ -51,7 +50,7 @@ make menuconfig
</div>
### Vérification via `/boot/config-xxx`
#### Vérification via `/boot/config-xxx`\
Les distributions basées sur Debian ont pour habitude de placer le fichier de
configuration ayant servi à compiler le noyau et ses modules dans le dossier
@ -60,7 +59,7 @@ fichiers initial (`initramfs-xxx`) et des symboles de débogage
`System.map-xxx`.
Ce fichier répertorie toutes les options qui ont été activées. Par rapport à
l'arbre présenté ci-dessus, vous devriez trouver :
l'arbre présenté ci-dessus, vous devriez trouver :
<div lang="en-US">
```
@ -81,7 +80,7 @@ CONFIG_CGROUP_NET_CLASSID=y
</div>
### Vérification via `/proc/config.gz`
#### Vérification via `/proc/config.gz`\
Dans la plupart des autres distributions, la configuration est accessible à
travers le fichier `/proc/config.gz`. Comme vous ne pouvez pas écrire dans
@ -91,12 +90,12 @@ Vous devez retrouver les mêmes options que celles de la section précédente.
## Présence des en-têtes
### Présence des en-têtes
Si vous utilisez un noyau standard fourni par votre distribution, les options
requises seront a priori déjà sélectionnées et vous n'aurez donc pas à compiler
votre propre noyau. Néanmoins, durant ce TP, nous allons nous interfacer avec
le noyau, il est donc nécessaire d'avoir les en-têtes de votre noyau.
votre propre noyau. Néanmoins, nous allons nous interfacer avec le noyau, il
est donc nécessaire d'avoir les en-têtes de votre noyau.
Sous Debian, vous pouvez les installer via le paquet au nom semblable à
`linux-headers`. Le paquet porte le même nom sous Arch Linux et ses dérivés.

12
tutorial/3/intro.md Normal file
View File

@ -0,0 +1,12 @@
\newpage
Statistiques et contrôle des processus
======================================
Maintenant que nous avons pu voir en détail comment utiliser Docker, nous
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
sur eux ou en imposant certaines restrictions.

View File

@ -15,7 +15,7 @@ mémoire est donc utilisée de manière plus efficace.
<https://www.kernel.org/doc/html/latest/vm/overcommit-accounting.html>.
Mais évidemment, cela peut donner lieu à des situations où le noyau n'est plus
en mesure de trouver de bloc physiquement disponible, alors qu'ils avaient
en mesure de trouver de blocs physiquement disponibles, alors qu'ils avaient
effectivement été alloués au processus. Pour autant, ce n'est pas une raison
pour tuer ce processus, car il est peut-être vital pour le système (peut-être
est-ce `init` qui est en train de gérer le lancement d'un nouveau daemon). On
@ -31,18 +31,19 @@ l'*Out-Of-Memory killer*.
Selon un algorithme dont on raconte qu'il ne serait pas basé entièrement sur
l'aléatoire[^oom-algo], un processus est tiré au sort (plus un processus occupe
de mémoire et plus il a de chance d'être tiré au sort) par l'OOM killer. Le
sort qui lui est réservé est tout simplement une mort brutale. Pour permettre
sort qui lui est réservé est tout simplement une mort brutale, pour permettre
au système de disposer à nouveau de mémoire disponible. Si cela n'est pas
suffisant, un ou plusieurs autres processus peuvent être tués à tour de rôle,
jusqu'à ce que le système retrouve sa sérénité.
[^oom-algo]: <https://linux-mm.org/OOM_Killer>
## Esquiver l'OOM killer
Au sein d'un *cgroup* *memory*, le fichier `memory.oom_control` peut être
utilisé afin de recevoir une notification du noyau avant que l'OOM-killer
ne s'attaque à un processus de ce groupe.
## 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
noyau avant que l'OOM-killer ne s'attaque à un processus de ce groupe.
Grâce à cette notification, il est possible de figer le processus pour
l'envoyer sur une autre machine. Et ainsi libérer la mémoire avant que l'OOM
@ -50,3 +51,11 @@ killer ne passe.
Jetez un œil à [cet article parru sur LWN](https://lwn.net/Articles/590960/) à
ce sujet.
## À vous de jouer {-}
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` ?

View File

@ -1,7 +1,25 @@
\newpage
Rendu
=====
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).
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é de rendu
Un service automatique s'occupe de réceptionner vos rendus, de faire les
vérifications nécessaires et de vous envoyer un accusé de réception (ou de
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
rejet).
Ce service écoute sur l'adresse <virli@nemunai.re>, c'est donc à cette adresse
@ -9,8 +27,10 @@ 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.
Par ailleurs, n'oubliez pas de répondre à
[l'évaluation du cours](https://virli.nemunai.re/quiz/6).
Afin d'orienter correctement votre rendu, ajoutez une balise `[TP3]` 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.
## Tarball
@ -25,15 +45,13 @@ pour chaque exercice) :
<div lang="en-US">
```
login_x-TP3/
login_x-TP3/escape.c
login_x-TP3/escape.c # SRS
login_x-TP3/procinfo.sh
login_x-TP3/suspend_schedule.sh
login_x-TP3/view_caps.c
login_x-TP3/monitor.sh
login_x-TP3/monitor_init.sh
login_x-TP3/telegraf.sh # SRS
login_x-TP3/telegraf_init.sh # SRS
login_x-TP3/syscall_filter.c
```
</div>
Les premières étapes du projet ne sont pas à rendre et feront l'objet
d'un rendu à part.

View File

@ -1,14 +1,14 @@
\newpage
Pseudos systèmes de fichiers
============================
----------------------------
## Rappels sur les points de montage
### Rappels sur les points de montage
Les systèmes Unix définissent le système de fichiers comme étant un arbre
unique partant d'une racine[^FHS] et où l'on peut placer au sein de son arborescence
des points de montage. Ainsi, l'utilisateur définit généralement deux points de
montage :
montage :
[^FHS]: Consultez
<https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard> pour
@ -26,27 +26,27 @@ et les fichiers des utilisateurs sont sur la troisième partition du premier
disque.
## Présentation des pseudos systèmes de fichiers
### Présentation des pseudos systèmes de fichiers
D'autres points de montage sont utilisés par le système : `/dev`, `/proc`,
`/tmp`, ... Ces points de montage vont, la plupart du temps, être montés par le
D'autres points de montage sont utilisés par le système : `/dev`, `/proc`,
`/tmp`, ... Ces points de montage vont, la plupart du temps, être montés par le
programme d'initialisation en utilisant des systèmes de fichiers virtuels, mis
à disposition par le noyau.
Ces systèmes sont virtuels, car ils ne correspondent à aucune partition d'aucun
disque : l'arborescence est créée de toute pièce par le noyau pour trier les
disque : l'arborescence est créée de toute pièce par le noyau pour trier les
informations mises à disposition, mais il n'est pas toujours possible d'y
apporter des modifications.
Linux emploie de nombreux systèmes de fichiers virtuels :
Linux emploie de nombreux systèmes de fichiers virtuels :
- `/proc` : contient, principalement, la liste des processus (`top` et ses
- `/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 ;
- `/sys` : contient des informations à propos du matériel (utilisées notamment
- `/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, ...) ;
- `/sys/firmware/efi/efivars` : pour accéder et modifier les variables de
clignottement des DELs, ...) ;
- `/sys/firmware/efi/efivars` : pour accéder et modifier les variables de
l'UEFI ;
- ...
@ -57,9 +57,9 @@ exemple, pour modifier les paramètres du noyau, on passe par le fichier
`/etc/sysctl.conf` et du programme `sysctl`.
### Consultation et modification
#### Consultation et modification\
La consultation d'un élément se fait généralement à l'aide d'un simple `cat` :
La consultation d'un élément se fait généralement à l'aide d'un simple `cat` :
<div lang="en-US">
```
@ -68,7 +68,7 @@ freeze mem
```
</div>
La modification d'un élément se fait avec `echo`, comme ceci :
La modification d'un élément se fait avec `echo`, comme ceci :
<div lang="en-US">
```bash
@ -76,15 +76,15 @@ La modification d'un élément se fait avec `echo`, comme ceci :
```
</div>
Vous devriez constater l'effet de cette commande sans plus attendre !
Vous devriez constater l'effet de cette commande sans plus attendre !
## Exercices
### Exercices
### `procinfo`
#### `procinfo`\
Explorons le pseudo système de fichiers `/proc` pour écrire un script qui va
afficher des informations sur un processus donné :
afficher des informations sur un processus donné :
<div lang="en-US">
```
@ -125,17 +125,17 @@ uts:[4026531838]
</div>
### `batinfo.sh`, `cpuinfo.sh`
#### `batinfo.sh`, `cpuinfo.sh`\
Explorons le pseudo système de fichiers `/sys` pour écrire un script
qui va, en fonction de ce que vous avez de disponible :
qui va, en fonction de ce que vous avez de disponible :
* nous afficher des statistiques sur notre batterie ;
* nous afficher des statistiques la fréquence de notre CPU.
* afficher des statistiques sur notre batterie ;
* afficher des statistiques la fréquence du CPU.
#### `batinfo.sh`
##### `batinfo.sh`\
Voici un exemple d'utilisation :
Voici un exemple d'utilisation :
<div lang="en-US">
```
@ -158,13 +158,13 @@ Remaining time: N/A
```
</div>
Pour les détails sur l'organisation de ce dossier, regardez :
Pour les détails sur l'organisation de ce dossier, regardez :
<https://www.kernel.org/doc/Documentation/power/power_supply_class.txt>.
#### `cpuinfo.sh`
##### `cpuinfo.sh`\
Voici un exemple d'utilisation :
Voici un exemple d'utilisation :
<div lang="en-US">
```
@ -185,33 +185,33 @@ Thermal throttle count: 0
```
</div>
N'hésitez pas à rajouter toute sorte d'information intéressantes !
N'hésitez pas à rajouter toute sorte d'information intéressantes !
### `rev_kdb_leds.sh`, `suspend_schedule.sh`
#### `rev_kdb_leds.sh`, `suspend_schedule.sh`\
Maintenant que vous savez lire des informations dans `/sys`, tentons d'aller
modifier le comportement de notre système. Au choix, réaliser l'un des scripts
suivant, en fonction du matériel dont vous disposez :
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 ;
* mettre en veille votre machine, en ayant programmé une heure de réveil.
#### `rev_kdb_leds.sh`
##### `rev_kdb_leds.sh`\
Si vous avez :
Si vous avez :
* numlock On,
* capslock Off,
* scrolllock Off ;
Après avoir exécuté le script, nous devrions avoir :
Après avoir exécuté le script, nous devrions avoir :
* numlock Off,
* capslock On,
* scrolllock On.
Voici un exemple d'utilisation :
Voici un exemple d'utilisation :
<div lang="en-US">
```
@ -222,7 +222,7 @@ Voici un exemple d'utilisation :
`input20` correspond à l'identifiant de votre clavier, sous
`/sys/class/input/`.
#### `suspend_schedule.sh`
##### `suspend_schedule.sh`\
Votre script prendra en argument l'heure à laquelle votre machine doit être
réveillée, avant de la mettre effectivement en veille.
@ -232,7 +232,7 @@ système de fichiers `/sys`. Il n'est pas question de faire appel à un autre
programme (vous pourriez cependant avoir besoin de `date(1)` pour faire les
calculs horaires).
Voici un exemple d'utilisation :
Voici un exemple d'utilisation :
<div lang="en-US">
```
@ -242,11 +242,15 @@ 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
est Windows, elle utilisera sans doute le fuseau horaire courant. Sinon, ce
sera UTC.
:::::
Un article très complet sur le sujet est disponible ici :
::::: {.more}
Un article très complet sur le sujet est disponible ici :
<https://www.linux.com/tutorials/wake-linux-rtc-alarm-clock/>
:::::

View File

@ -12,7 +12,7 @@ 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'appel 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
@ -61,7 +61,7 @@ exécutée en cas de faute.
Notons que les processus fils issus (`fork(2)` ou `clone(2)`) d'un processus
auquel est appliqué un filtre `seccomp`, héritent également de ce filtre.
La construction de ce filtre est faite de manière programatique, via
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 :

View File

@ -12,7 +12,7 @@ abstract: |
\vspace{1em}
Certains éléments de ce TP sont à rendre à <virli@nemunai.re> au
plus tard le jeudi 12 novembre 2020 à 12 h 42. Consultez la
plus tard le mercredi 6 octobre 2020 à 23 h 42. Consultez la
dernière section de chaque partie pour plus d'informations sur les
éléments à rendre.