Pourquoi ne puis-je pas écraser mon système avec une fourche piégée?

54

Récemment, j'ai déterré des informations sur les processus sous GNU / Linux et j'ai rencontré la fameuse bombe à fourche:

:(){ : | :& }; :

Théoriquement, il est supposé se dupliquer à l'infini jusqu'à ce que le système manque de ressources ...

Cependant, j'ai essayé de tester à la fois sur une distribution CLI Debian et une distribution graphique Mint , et cela ne semble pas avoir beaucoup d'incidence sur le système. Oui, il y a des tonnes de processus qui sont créés, et après un moment, je lis dans la console des messages tels que:

bash: fork: ressource temporairement indisponible

bash: fork: réessayer: aucun processus enfant

Mais après un certain temps, tous les processus sont tués et tout retourne à la normale. J'ai lu que la commande ulimit définissait un nombre maximal de processus par utilisateur, mais je ne parais pas être en mesure de l'augmenter vraiment.

Quelles sont les protections système contre les bombes à la fourche? Pourquoi ne se reproduit-il pas jusqu'à ce que tout soit gelé ou au moins beaucoup décalé? Y a-t-il un moyen de vraiment écraser un système avec une bombe fourchue?

Plancton
la source
2
Quel est votre PID maximum actuellement?
dsstorefile1
5
Notez que vous ne "planterez" pas votre système en utilisant une bombe à retardement ... comme vous l'avez dit, vous épuiserez vos ressources et serez incapable de générer de nouveaux processus, mais le système ne devrait pas se bloquer
Josh
2
Que se passe-t-il si vous courez à la :(){ :& :; }; :place? Est-ce qu'ils finissent tous par se faire tuer? Qu'en est- il :(){ while :& do :& done; }; :?
mtraceur
Votre cette question merveilleuse m'a convaincu de repenser mon vote précédent "laissez de côté". Cependant, "I" est toujours en majuscule en anglais, ne l'écrivez pas mal, s'il vous plaît.
user259412 le

Réponses:

85

Vous avez probablement une distribution Linux qui utilise systemd.

Systemd crée un groupe de contrôle pour chaque utilisateur, et tous les processus d'un utilisateur appartiennent au même groupe de contrôle.

Cgroups est un mécanisme Linux permettant de définir des limites sur les ressources système, telles que le nombre maximal de processus, les cycles de processeur, l'utilisation de la mémoire vive, etc. Il s'agit d'une couche de limitation des ressources différente, plus moderne que celle ulimit(qui utilise l'appel getrlimit()système).

Si vous exécutez systemctl status user-<uid>.slice(qui représente le groupe de contrôle de l'utilisateur), vous pouvez voir le nombre actuel et maximal de tâches (processus et threads) autorisés dans ce groupe de contrôle.

$ systemctl status user- $ UID.slice
● user-22001.slice - Tranche d'utilisateur de l'UID 22001
   Chargé: chargé
  Drop-In: /usr/lib/systemd/system/user-.slice.d
           └─10-defaults.conf
   Actif: Actif depuis lun. 2018-09-10 17:36:35 EEST; Il y a 1 semaines 3 jours
    Tâches: 17 (limite: 10267)
   Mémoire: 616,7 M

Par défaut, le nombre maximal de tâches que systemd autorisera pour chaque utilisateur correspond à 33% du "maximum du système" ( sysctl kernel.threads-max); cela équivaut généralement à environ 10 000 tâches. Si vous voulez changer cette limite:

  • Dans Systemd v239 et versions ultérieures, la valeur par défaut de l'utilisateur est définie via TasksMax = dans:

    /usr/lib/systemd/system/user-.slice.d/10-defaults.conf
    

    Pour ajuster la limite pour un utilisateur spécifique (qui sera appliqué immédiatement ainsi que stocké dans /etc/systemd/system.control), exécutez:

    systemctl [--runtime] set-property user-<uid>.slice TasksMax=<value>
    

    Les mécanismes habituels de substitution des paramètres d'une unité (tels que systemctl edit) peuvent également être utilisés ici, mais ils nécessiteront un redémarrage. Par exemple, si vous souhaitez modifier la limite pour chaque utilisateur, vous pouvez créer /etc/systemd/system/user-.slice.d/15-limits.conf.

  • Dans Systemd v238 et versions antérieures, les paramètres utilisateur par défaut sont définis via UserTasksMax = in /etc/systemd/logind.conf. Changer la valeur nécessite généralement un redémarrage.

Plus d'informations à ce sujet:

Hkoof
la source
5
Et 12288 processus (moins ce qui était déjà créé avant la bombe) ne faisant rien sauf essayer de créer un nouveau, n'a pas vraiment d'impact sur un système moderne.
Mât
13

Cela ne plantera plus les systèmes Linux modernes de toute façon.

Il crée une horde de processus mais ne brûle pas vraiment autant de ressources processeur, car les processus deviennent inactifs. Vous manquez de logements dans la table de processus avant de manquer de RAM maintenant.

Si Hkoof ne vous limite pas, c’est la modification suivante qui réduit les systèmes:

:(){ : | :& : | :& }; :
Josué
la source
5
Cela dépend vraiment de ce que vous considérez comme un "crash" du système. Manquer d'emplacements dans la table de processus mettra un système à genoux dans la plupart des cas, même s'il ne provoque pas complètement une panique du noyau.
Austin Hemmelgarn le
4
@ AustinHemmelgarn: C'est pourquoi les systèmes intelligents réservent les 4 derniers identifiants de processus pour root.
Josué
2
Pourquoi les processus iraient-ils "au ralenti"? Chaque processus créé est dans une récursion infinie consistant à créer plus de processus. Ainsi, il passe beaucoup de temps en surcharge d’appel système (sans forkcesse) et le reste de son temps à effectuer l’appel de la fonction (en utilisant de manière incrémentielle plus de mémoire pour chaque appel de la pile d’appel du shell).
mtraceur
4
@mtraceur: Cela ne se produit que lorsque le forking commence à échouer.
Josué
1
Oh, je le récupère. Je modélisais dans ma tête la logique d'une implémentation légèrement différente d'une bombe à la bombe (comme ceci:) :(){ :& :; }; :au lieu de celle de la question. En réalité, je n'ai pas complètement réfléchi au flux d'exécution de l'archétype comme donné.
mtraceur
9

Dans les années 90, j'en ai accidentellement déclenché une. J'avais par inadvertance défini le bit d'exécution sur un fichier source C contenant une commande fork (). Quand j'ai double-cliqué dessus, csh a essayé de l'exécuter plutôt que de l'ouvrir dans un éditeur comme je le voulais.

Même à ce moment-là, le système n'a pas été bloqué. Unix est suffisamment robuste pour que votre compte et / ou le système d'exploitation ait une limite de processus. Ce qui se produit à la place est que cela devient extrêmement lent et que tout ce qui doit démarrer un processus est susceptible d’échouer.

En coulisse, la table des processus se remplit de processus qui essaient de créer de nouveaux processus. Si l'un d'entre eux se termine (soit en raison d'une erreur sur le fork, parce que la table de processus est pleine, soit à cause d'un opérateur désespéré qui tente de rétablir l'intégrité de son système), l'un des autres processus en lancera un nouveau à remplir. le vide.

La "bombe à la bombe" est fondamentalement un système de processus involontairement auto-réparateur dans le but de garder votre table de processus complète. La seule façon de l'arrêter est de les tuer tous en même temps.

TED
la source
1
Les tuer tous en même temps est plus facile que vous ne le pensez - SIGSTOP les tous d'abord.
Score_Under
2
@Score_Under - J'espère que vous me pardonnerez si je ne me précipite pas immédiatement vers mon Harris Nighthawk le plus proche pour voir si cela aurait résolu le problème. Je pense que juste obtenir un PID puis l'envoyer le signal avant qu'il meure de l'échec de la fourche et qu'un autre le remplace peut être un défi, mais je devais l'essayer.
TED
@TED ​​kill -9 -1 est peut-être votre ami ici (avec le même utilisateur que celui qui exécute le fork bombe; pas avec root).
Andreas Krey
@AndreasKrey - Ce drapeau n'a pas l'air familier, alors je doute que Nighthawk l'ait eu.
TED
1
@TED: -1n'est pas un drapeau. killprend seulement une option puis arrête l'analyse des options. Cela élimine l'identifiant du processus -1, qui est un alias pour tous les processus.
Josué