Journal ulimits: appliquer des limitations de ressources sans PAM

Posté par (page perso) . Licence CC by-sa
28
4
mai
2015

Sommaire

Je présente ici un petit outil sans prétention de mon cru, ulimits, qui permet d’appliquer des limitations de ressources aux utilisateurs de systèmes dépourvus de PAM.

Les limitations de ressources

Les « limitations de ressources » (resource limits) sont un mécanisme permettant d’empêcher un utilisateur de faire un usage abusif des ressources d’une machine. Il est ainsi possible d’empêcher un utilisateur de créer trop de processus, de créer des fichiers trop gros, de poser trop de verrous, de consommer trop de CPU, etc.

Pour voir la liste des ressources ainsi limitables, ainsi que les limitations actuellement appliquées à votre compte utilisateur, vous pouvez utiliser la commande shell ulimit (bash, zsh) ou limit (csh) :

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15502
max locked memory       (kbytes, -l) 256000
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 95
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15502
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

La même commande peut servir à modifier les limitations, mais vous ne pouvez repousser les limites que si vous avez les droits du superutilisateur — en tant qu’utilisateur normal, vous ne pouvez que réduire vos droits en fixant de nouvelles limites inférieures aux limites déjà en vigueur.

Comment assigner des limitations à un utilisateur

Les limitations de ressources sont attachées à un processus ; elles sont héritées par le processus fils lors d’un fork et préservées lors d’un exec. Du coup, le meilleur moment pour appliquer des limitations à un utilisateur et à tous ses processus, c’est lors de la connexion initiale de ce dernier.

Sur la plupart des distributions GNU/Linux, c’est un module PAM, pam_limits, qui se charge d’appliquer les limitations de ressources à la connexion d’un utilisateur (quel que soit la méthode de connexion, du moment qu’elle est « PAM-ifiée »). L’administrateur peut définir les limitations qu’il souhaite imposer dans le fichier /etc/security/limits.conf.

Par exemple, pour donner aux utilisateurs du groupe audio la possibilité de lancer des programmes en mode temps-réel, on ajoutera dans ce fichier la ligne suivante :

@audio  soft  rtprio  95

(La limitation par défaut pour la priorité temps-réel est généralement de 0, ce qui concrètement interdit le mode temps-réel.)

Si votre système utilise PAM, vous n’avez pas besoin d’aller plus loin : le module pam_limits et son fichier /etc/security/limits.conf sont tout ce qu’il vous faut. Merci quand même d’avoir lu jusqu’ici, si vous ne connaissiez pas les limitations de ressources j’espère vous avoir fait découvrir quelque chose d’utile.

Le programme que je veux vous présenter aujourd’hui s’adresse à ceux qui utilisent une distribution ne fournissant pas Linux-PAM (les deux du fond, relevez la tête, c’est à vous que je parle).

Pas de PAM ? Pas de panique !

Sur les systèmes sans PAM, les limitations de ressources peuvent être définies dans un fichier /etc/limits, obéissant au même principe que /etc/security/limits.conf mais à la syntaxe un peu plus dense et plus absconse. Par exemple, la ligne suivante :

@audio O95M256000

fixe pour les utilisateurs du groupe audio la priorité temps-réel maximale à 95, et la quantité maximale de « mémoire verrouillable » (mémoire que le noyau s’interdit de transférer dans le swap, et maintient obligatoirement dans la mémoire physique) à 256 Mo.

En absence de PAM, c’est /bin/login, le programme utilisé pour se connecter à une console texte, qui applique les limitations définies dans le fichier /etc/limits.

Le problème, c’est que seul /bin/login tient compte de ce fichier /etc/limits. Si vous ne passez pas par /bin/login pour vous connecter (par exemple, si vous passez par un gestionnaire de connexion graphique comme xdm), les limitations définies par l’administrateur dans /etc/limits ne seront pas appliquées, et ce seront les limitations par défaut imposées par le noyau qui seront en vigueur.

C’est là que ulimits, le programme que je présente dans ce journal, devient intéressant pour les deux personnes du fond de la salle.

Ulimits

Le programme ulimits permet à un utilisateur s’étant connecté autrement que par /bin/login de lire le fichier /etc/limits et d’appliquer les limitations de ressources qui y sont définies.

L’utilisation typique (c’est-à-dire, celle du seul utilisateur connu de ce programme, à savoir moi-même) consiste à invoquer ulimits dans son script ~/.xsession, juste avant de lancer le gestionnaire de fenêtres :

#!/bin/sh

# Apply resource limits
ulimits

# Start the window manager
exec /usr/bin/awesome

L’invocation de ulimits appliquera les limitations de ressources au shell en train d’exécuter le script ~/.xsession, et ces limitations seront ensuite transmises au gestionnaire de fenêtres (ici Awesome), et à travers lui à tous les processus lancés par l’utilisateur au cours de sa session.

Avertissement
Pour fonctionner, ulimits doit appartenir à root avec le bit setuid positionné. C’est nécessaire d’une part pour pouvoir lire le contenu du fichier /etc/limits (limits(5) nous apprend que ce fichier ne doit être lisible que par le superutilisateur), et d’autre part pour pouvoir fixer les limitations de ressources à des valeurs arbitraires potentiellement supérieures à celles en vigueur au moment où le programme est appelé.

L’application des limitations de ressources au shell qui a invoqué ulimits, comme dans l’exemple ci-dessus, nécessite l’appel système prlimit(2), introduit dans Linux 2.6.36. En l’absence de cet appel système (noyau non-Linux ou Linux antérieur à 2.6.36), ulimits ne peut appliquer les limitations qu’à son propre processus. Dans ce cas, on peut obtenir le même effet que ci-dessus en demandant à ulimits d’exécuter lui-même le gestionnaire de fenêtres, afin que celui-ci hérite des limitations :

#!/bin/sh

# Start the window manager
ulimits /usr/bin/awesome

Si cet outil vous intéresse, le code est là :

  • # Curiosité...

    Posté par (page perso) . Évalué à 4.

    Ma curiosité est piquée ….
    A part de la distrib "custom" ayant pour vocation d'être embarquée, quelle distribution GNU/Linux moderne n'embarque pas PAM actuellement ?
    (Je me souviens avoir bossé il y a environ 10 ans sur PAM et c'était globalement très très répandu).

    • [^] # Re: Curiosité...

      Posté par . Évalué à 8.

      Slackware

      "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

    • [^] # Re: Curiosité...

      Posté par . Évalué à 5.

      Slackware refuse (refusait ?) d'intégrer PAM le considérant bloated et trop buggé

    • [^] # Re: Curiosité...

      Posté par (page perso) . Évalué à 7.

      Slackware comme déjà dit, et il y a apparemment des distributions qui le fournissent mais laissent la possibilité de s’en passer (c’est le cas de SourceMage, où ulimits est d’ailleurs empaqueté sous la forme d’un « sort » dans le « grimoire »).

    • [^] # Re: Curiosité...

      Posté par (page perso) . Évalué à 6.

      Quelle distribution GNU/Linux moderne n’embarque pas PAM actuellement ?

      (3×)Slackware

      Je suis étonné que personne n’ait saisi une telle perche : « on a demandé une distribution moderne… »

      Serait-ce l’ultime déchéance d’une distribution qui est tellement oubliée qu’on n’a même plus le cœur à vanner ses utilisateurs ?

      (Tss, DLFP n’est plus ce qu’il était. Voilà qu’il faut se moquer soi-même de sa distribution à présent.)

      • [^] # Re: Curiosité...

        Posté par . Évalué à 2. Dernière modification le 06/05/15 à 23:40.

        Slackware a toujours été la distribution à intégrer les dernières évolutions du noyau ou de l'userland système, à attendre que les technologies aient mûri. Ce n'est aucunement, en tous cas moi je ne le vois pas comme ça, le signe que cette distribution n'est pas moderne, c'est clairement le parti pris depuis le début… Je pense que c'est assumé. Slackware reste un monument dans le paysage des distributions GNU/Linux, pour plusieurs bonnes raisons.

        Ce sera très probablement la dernière à adopter systemd, si le besoin s'en faisait vraiment ressentir, elle n'est peut-être pas moderne mais elle est éternelle !

        Je trouve qu'une distribution comme Arch a repris l'un des concepts intéressant de Slackware qui est qu'on essaye de toucher le moins possible à l'upstream et que les efforts de configuration et d'intégration sont laissé au soin de l'administrateur/utilisateur (guidé par un excellente documentation, bien entendu).

      • [^] # Re: Curiosité...

        Posté par . Évalué à 3.

        Vanner les vieux, c'est (très) moche…

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.