Limiter les accès aux ressources (CPU, RAM) sur sa machine

Introduction

Il y a plusieurs mois de cela, pour ne pas dire années, j’avais testé (étant un jeune padawan sous linux) une fork bomb sur ma machine. A ma grande surprise, j’avais observé l’agonie de ma machine ne me laissant que le choix de redémarrer sauvagement. Surprise, car j’aurai attendu qu’une distribution populaire soit protégée de ce type d’attaque basique.

Très récemment, j’ai été reconfronté à un problème qui m’arrive tous les 36 du mois, une grosse fuite mémoire replissant en un éclair la ram, puis s’attaquant à la swap. Avec un peu d’habilité, on peut tuer le processus à temps avant que cela ne devienne fatal… mais on a déjà vu moins sportif. Le fautif, vous le connaissez peut être, c’est flash. (au passage il faut que je (re)teste gnash pour voir si on peut s’en passer…)

Bref, ces deux problèmes vous semblent peut être différents mais on pourrait les résoudre simplement en limitant l’accès des processus aux ressources de la machine. Ici, nous voyons que dans le premier cas, c’est le nombre de processus et dans le second la quantité de ram consommé, mais ce pourrait être aussi la part de CPU, la solution resterait valable.

Fork bomb

Qu’est ce qu’une fork bomb ? C’est relativement simple. Sous Unix, on peut très facilement (et c’est très puissant) « forker » un processus, c’est à dire générer un processus fils qui va tourner en parallèle du père. Astuce sympa que les amateurs de scripts pour réaliser des tâches répétitives doivent connaitre. Bref, maintenant, imaginez que le père crée des fils de manière infinie et que ces fils se répliquent à leur tour. On imagine très vite les conséquences… Le nombre de processus croit exponentiellement. La conséquence : un déni de service : la machine de répond plus.

Il est possible de créer des fork bombs dans de nombreux langages. Je vais m’appuyer sur du C.

#include<stdlib.h>
#include<stdio.h>
int main(void)
{
long count = 0;
while (count<10)
{
fork();
count++;
printf(« %d  »,count);
}
return 0;
}
J’ai limité la boucle à une dizaine de tours, soit 10*10=100 processus créés. (conseil, allez-y doucement ;) )

Remplissage de la mémoire

Tant que j’y suis à donner des petits bouts de code, voici celui qui va venir prendre de la mémoire.

#include<stdlib.h>
#include<stdio.h>
int main(void)
{
long count = 0;
while (count<500000)
{
void *var = malloc(1000)
count++;
printf(« %d  »,count);
}
return 0;
}
Ici, à chaque tour de boucle, j’alloue 1Ko que je ne libère pas (c’est le but hein…). L’exécution de ce code n’est pas trop dangereuse au sens où c’est assez facilement contrôlable.
Dans les deux cas, un top vous permet d’observer les effets. Soit l’augmentation du nombre de processus pour le premier, soit l’occupation de la ram (et peut être la swap) dans le second.

Non à la folie

Maintenant que nous avons de quoi tester et reproduire les choses, la question est : quelle est la parade. Regardons du coté de ulimit.

ulimit -a

permet de voir les règles actuelles. Pour la fork bomb, nous allons regarder du coté de

max user processes

qui chez moi est autour de 8000. C’est beaucoup (pour un netbook…). Au démarrage, je n’ai même pas 200 processus en tout sur ma machine. On peut le diminuer à l’aide de la commande

ulimit -u 300

L’exécution d’une fork bomb dans ce cas est stoppée par un message indiquant que nous avons atteint la limite. Voilà le premier problème résolu. Nous verrons dans la suite comment pérenniser les choses dans un fichier de config.

Et pour l’accès mémoire de ce foutu flash ? Ce n’est pas loin :

virtual memory

est la bonne variable, ulimited chez moi. On peut essayer un

ulimit -v 260000

et là, on voit à nouveau que cela fonctionne très bien. Le processus glouton en mémoire n’est pas stoppé, mais il est limité en accès mémoire comme on peut le voir en jouant avec le code ci-dessus.

Pérenniser le garde-fou

Pour conserver nos modifications, nous nous tournons vers le fichier /etc/security/limits.conf. En commentaire est donnée la syntaxe de manière claire.

L’explication en ce qui concerne soft et hard est très bien faite . On peut laisser à l’utilisateur le soin de bouger la limite avec une certaine liberté…

Les deux variables dont nous avons parlé sont :

#        - nproc – max number of processes

#        - as – address space limit (KB)

… il n’y a plus qu’à. On peut limiter des groupes, des utilisateurs en particulier… sans soucis.

Dans la liste, on remarquera aussi la possibilité de jouer avec le temps CPU, la priorité des processus… ce peut être utile.

Pour ma part, il ne me reste plus qu’à trouver les valeurs pertinentes pour les paramètres. J’espère que cet article vous sera utile. :)

PS : pour ceux qui ne trouveraient pas le fichier limits.conf, installez le paquet pam.


Vus : 761
Publié par François : 67