Warum kann ich mein System nicht mit einer Gabelbombe zum Absturz bringen?

54

Kürzlich habe ich Informationen über Prozesse in GNU / Linux ausgegraben und bin auf die berüchtigte Gabelbombe gestoßen:

:(){ : | :& }; :

Theoretisch soll es sich unendlich duplizieren, bis dem System die Ressourcen ausgehen ...

Ich habe jedoch versucht, sowohl auf einer CLI Debian- als auch einer GUI Mint- Distribution zu testen , und es scheint das System nicht wesentlich zu beeinträchtigen. Ja, es werden Unmengen von Prozessen erstellt, und nach einer Weile lese ich Konsolenmeldungen wie:

bash: fork: Ressource vorübergehend nicht verfügbar

bash: fork: retry: Keine untergeordneten Prozesse

Aber nach einiger Zeit werden alle Prozesse einfach abgebrochen und alles normalisiert sich wieder. Ich habe gelesen, dass das ulimit eine maximale Anzahl von Prozessen pro Benutzer festlegt , aber ich kann es anscheinend nicht wirklich weit anheben.

Was ist der Schutz des Systems gegen eine Gabelbombe? Warum repliziert es sich nicht, bis alles einfriert oder zumindest viel nacheilt? Gibt es eine Möglichkeit, ein System mit einer Gabelbombe zum Absturz zu bringen?

Plancton
quelle
2
Was ist Ihre derzeit eingestellte maximale PID?
dsstorefile1
5
Beachten Sie, dass Sie Ihr System nicht mit einer Gabelbombe "zum Absturz bringen" ... wie Sie sagten, werden Sie Ressourcen erschöpfen und keine neuen Prozesse mehr erzeugen können, aber das System sollte nicht abstürzen
Josh
2
Was passiert, wenn du :(){ :& :; }; :stattdessen rennst? Werden sie schließlich auch alle getötet? Was ist :(){ while :& do :& done; }; :?
mtraceur
Ihre wunderbare Frage hat mich überzeugt, meine bisherige "Leave Closed" -Abstimmung zu überdenken. "I" ist jedoch immer in Großbuchstaben geschrieben, bitte schreibe es nicht mehr schlecht.
User259412

Antworten:

85

Sie haben wahrscheinlich eine Linux-Distribution, die systemd verwendet.

Systemd erstellt für jeden Benutzer eine cgroup, und alle Prozesse eines Benutzers gehören derselben cgroup an.

Cgroups ist ein Linux-Mechanismus, mit dem Systemressourcen wie die maximale Anzahl von Prozessen, CPU-Zyklen, RAM-Nutzung usw. begrenzt werden können. Dies ist eine andere, modernere Ebene der Ressourcenbeschränkung als ulimit(die den getrlimit()Syscall verwendet).

Wenn Sie ausführen systemctl status user-<uid>.slice(was die cgroup des Benutzers darstellt), können Sie die aktuelle und maximale Anzahl von Aufgaben (Prozesse und Threads) anzeigen, die in dieser cgroup zulässig sind.

$ systemctl status user- $ UID.slice
● user-22001.slice - Benutzer-Slice der UID 22001
   Geladen: Geladen
  Drop-In: /usr/lib/systemd/system/user-.slice.d
           └─10-defaults.conf
   Aktiv: Aktiv seit Mo 2018-09-10 17:36:35 EEST; Vor 1 Woche 3 Tage
    Aufgaben: 17 (Limit: 10267)
   Speicher: 616,7M

Standardmäßig beträgt die maximale Anzahl von Aufgaben, die systemd für jeden Benutzer zulässt, 33% des "systemweiten Maximums" ( sysctl kernel.threads-max). Das sind in der Regel ~ 10.000 Aufgaben. Wenn Sie dieses Limit ändern möchten:

  • In systemd v239 und höher wird der Benutzerstandard über TasksMax = in festgelegt:

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

    Führen Sie Folgendes aus, um das Limit für einen bestimmten Benutzer anzupassen (das sofort angewendet und in /etc/systemd/system.control gespeichert wird):

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

    Die üblichen Mechanismen zum Überschreiben der Einstellungen einer Einheit (z. B. systemctl edit) können auch hier verwendet werden, erfordern jedoch einen Neustart. Wenn Sie beispielsweise das Limit für jeden Benutzer ändern möchten , können Sie es erstellen /etc/systemd/system/user-.slice.d/15-limits.conf.

  • In systemd v238 und früheren Versionen wird der Benutzerstandard über UserTasksMax = in festgelegt /etc/systemd/logind.conf. Das Ändern des Werts erfordert im Allgemeinen einen Neustart.

Mehr Infos dazu:

Hkoof
quelle
5
Und 12288 Prozesse (abzüglich dessen, was bereits vor der Bombe erzeugt wurde), die nichts anderes tun, als zu versuchen , ein neues zu erstellen, wirken sich nicht wirklich auf ein modernes System aus.
Mast
13

Dadurch werden moderne Linux-Systeme sowieso nicht mehr zum Absturz gebracht.

Es erzeugt eine Vielzahl von Prozessen, verbrennt jedoch nicht so viel CPU, da die Prozesse im Leerlauf laufen. Sie haben keine Slots in der Prozesstabelle mehr, bevor Ihnen jetzt der Arbeitsspeicher ausgeht.

Wenn Sie nicht auf Gruppen beschränkt sind, wie Hkoof betont, werden die Systeme durch die folgende Änderung immer noch heruntergefahren:

:(){ : | :& : | :& }; :
Joshua
quelle
5
Dies hängt wirklich davon ab, was Sie als Absturz des Systems ansehen. Wenn in der Prozesstabelle keine Slots mehr vorhanden sind, geht das System in den meisten Fällen in die Knie, auch wenn es nicht vollständig zu einer Kernel-Panik führt.
Austin Hemmelgarn
4
@AustinHemmelgarn: Aus diesem Grund reservieren weise Systeme die letzten 4 Prozess-IDs für root.
Joshua
2
Warum würden die Prozesse "im Leerlauf" laufen? Jeder gegabelte Prozess befindet sich in einer unendlichen Rekursion, bei der mehr Prozesse erstellt werden. Daher verbringt es viel Zeit mit dem Systemaufruf-Overhead ( forkimmer wieder) und den Rest seiner Zeit mit dem Funktionsaufruf (vermutlich inkrementell mit mehr Speicher für jeden Aufruf im Aufruf-Stack der Shell).
mtraceur
4
@mtraceur: Dies passiert nur, wenn das Gabeln fehlschlägt.
Joshua
1
Oh, ich nehme es zurück. Ich modellierte die Logik einer etwas anderen Gabelbombenimplementierung in meinem Kopf (wie folgt:) :(){ :& :; }; :anstelle der in Frage kommenden. Ich habe den Ablauf der Ausführung des Archetypischen noch nicht vollständig durchdacht.
mtraceur
9

In den 90ern habe ich versehentlich eine davon auf mich selbst losgelassen. Ich hatte versehentlich das Ausführungsbit für eine C-Quelldatei gesetzt, die einen fork () -Befehl enthielt. Wenn ich darauf doppelklickte, versuchte csh, es auszuführen, anstatt es in einem Editor zu öffnen, wie ich es wollte.

Selbst dann hat es das System nicht zum Absturz gebracht. Unix ist robust genug, dass Ihr Konto und / oder das Betriebssystem ein Prozesslimit haben. Stattdessen wird es sehr träge und alles, was zum Starten eines Prozesses benötigt wird, schlägt wahrscheinlich fehl.

Hinter den Kulissen füllt sich die Prozesstabelle mit Prozessen, die versuchen, neue Prozesse zu erstellen. Wenn einer von ihnen beendet wird (entweder, weil ein Fehler in der Verzweigung vorliegt, weil die Prozesstabelle voll ist, oder weil ein verzweifelter Bediener versucht, die Vernunft in seinem System wiederherzustellen), gibt einer der anderen Prozesse fröhlich einen neuen aus, der gefüllt werden soll das Nichts.

Die "Gabelbombe" ist im Grunde ein unbeabsichtigtes, sich selbst reparierendes System von Prozessen, um Ihren Prozesstisch voll zu halten. Der einzige Weg, dies zu stoppen, besteht darin, sie alle auf einmal zu töten.

TED
quelle
1
Sie alle auf einmal zu töten ist einfacher als Sie denken - SIGSTOPPEN Sie sie alle zuerst.
Score_Under
2
@Score_Under - Ich hoffe, Sie werden mir vergeben, wenn ich nicht sofort zu meinem nächsten Harris Nighthawk renne, um zu sehen, ob das Problem dort behoben worden wäre. Ich denke, nur eine PID zu bekommen und ihr das Signal zu senden, bevor es von der ausgefallenen Gabelung ausgeht und eine andere es findet, könnte eine Herausforderung sein, aber ich müsste es ausprobieren.
TED
@TED ​​kill -9 -1 ist möglicherweise dein Freund hier (mit demselben Benutzer, der die Gabelbombe ausführt, nicht mit root).
Andreas Krey
@AndreasKrey - Diese Flagge kommt mir nicht bekannt vor, also bezweifle ich, dass Nighthawk sie in den 90ern hatte.
TED
1
@TED: -1ist keine Flagge. killNimmt nur eine Option und stoppt dann das Parsen der Optionen. Dadurch wird die Prozess-ID beendet. Dies -1ist ein Alias ​​für alle Prozesse.
Joshua