fork-бомба

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку
Рекурсивне породження процесів, яке веде до відмова в обслуговуванні або падінню системи

Fork-бомба — шкідлива або помилково написана програма, яка нескінченно створює свої копії (системним викликом fork()), який, зазвичай, також створює свої копії і т. д.

Виконання такої програми може викликати велике навантаження обчислювальної системи або навіть відмова в обслуговуванні внаслідок нестачі системних ресурсів (дескрипторів процесів, пам'яті, процесорного часу), що і є ціллю.

Програма класичної fork-бомби (написаної на мові Сі) виглядає так:

 #include <unistd.h>
 
 int main()
 {
   while(1)
     fork();
 }

Схожими випадками витоку системних ресурсів є програми, які породжують зомбі. Однак, якщо більшість fork-бомб створюються навмисне, то ці проблеми, зазвичай, є результатом неуважності або некомпетентності програміста.

Історія[ред. | ред. код]

Близько 1978 року був створений ранній варіант вилки бомби під назвою wabbit System / 360. Це може відбутися з аналогічної атаки під назвою 'RABBITS' , яку повідомляють з 1969 р.

Опис[ред. | ред. код]

Fork-бомба породжує велику кількість власних копій і тим самим намагається заповнити вільне місце в списку активних процесів операційної системи. Після заповнення списку процесів стає неможливим старт корисної програми. Навіть якщо який-небудь інший процес припинить роботу і місце в списку процесів звільниться, то старт корисної програми малоймовірний, тому що безліч інших копій fork-бомби вже чекають можливості запустити свою чергову копію.

Крім заповнення списку процесів, можливі також стратегії заповнення віртуальної пам'яті, процесорного часу, сокетів і інших системних ресурсів. Результатом вичерпання цих ресурсів стає уповільнення роботи або практично зупинка операційної системи і / або корисних програм (зависання комп'ютера).

Fork-бомба може бути отримана і в результаті помилки при сумлінному програмуванні. Наприклад, програма, яка слухає мережевий порт, може при отриманні мережевого пакету або встановленні з'єднання «впасти» в нескінченний цикл створення своїх копій для обробки пакета або з'єднання. Проста помилка програмування може привести до витоку пам'яті або до наслідків, характерним для результатів роботи fork-бомби.

Приклади fork-бомб на різних мовах програмування[ред. | ред. код]

Bash:[1]

 :(){ :|:& };:

Perl:

 fork while fork

Python:

import os
 
while True:
    os.fork()

Ruby:

fork while fork

Інший варіант:

loop { fork }

PHP:

<?php 

while(true) {
    pcntl_fork();
}

Пакетний файл Microsoft Windows:

:s
start %0
goto :s

Інший варіант:

start %0 %0

Варіант на VB.NET

Do System.Diagnostics.Process.Start(System.Reflection.Assembly.GetExecutingAssembly().Location) Loop While True

Труднощі ліквідації[ред. | ред. код]

У разі успішного спрацьовування fork-бомби стає важким або практично неможливим відновити нормальну роботу ЕОМ без перезавантаження, так як єдиний спосіб припинити роботу fork-бомби - це одночасне припинення роботи всіх працюючих копій fork-бомби. У більшості реалізацій операційних систем виклик команди для припинення роботи процесу вимагає запуску нового процесу, що в умовах успішно працює fork-бомби неможливо.

Однак, на практиці деякі fork-бомби не вимагають таких радикальних заходів і можуть бути знищені без необхідності перезавантаження. Розглянемо, наприклад, випадок бомби з прикладу вище:

 :(){ :|:& };:

Особливість цього коду в тому, що він не зациклюється після неуспішного породження своїх копій, а завершує роботу. В результаті список процесів постійно знаходиться на межі заповнення: одна з копій fork-бомби завершується, і місце, що звільняється тут же займається новоствореним процесом з іншої копії fork-бомби. Стає можливим конкурувати з fork-бомбою за захоплення місця в списку процесів. Тоді, можливо, рано чи пізно запустити команду для одночасного знищення всіх копій-fork бомби або запустити безпечну програму, яка буде поступово «відвойовувати» місце в списку процесів до завершення роботи останнього процесу fork-бомби. Приклад такої безпечної програми на zsh:

 while (sleep 100 &!) do; done

Запобігання[ред. | ред. код]

Один із способів запобігання негативним наслідкам роботи fork-бомби - примусове обмеження кількості процесів, які користувач може запустити одночасно. Також можуть бути обмежені кількість виділеної віртуальної пам'яті і інші системні ресурси. При вичерпанні максимуму доступних процесів спроба процесу створити новий процес зазнає невдачі. Максимум що запускаються процесів повинен бути таким, щоб він дозволяв запустити розумне корисне кількість програм, але не приводив до краху системи при одночасному запуску fork-бомби від всіх користувачів системи.

Необхідно відзначити, що обмеження кількості процесів саме по собі не запобігає запуск fork-бомби, а лише направлено на мінімізацію можливої ​​шкоди в разі її спрацьовування.

Інше рішення проблеми - інтелектуальне розпізнавання fork-бомби засобами самої операційної системи, але це рішення не знайшло широкого застосування.

Існує і така трудність, що якщо fork-бомба займає весь доступний процесорний час, то результати її роботи можуть бути катастрофічними не тільки на однопроцесорній, але і на багатопроцесорної системі, навіть при обмеженні числа процесів. Наприклад, якщо число процесорів 16, а максимум кількості запущених процесів 100, то на кожен процесор буде припадати в середньому 6-7 працюючих екземплярів fork-бомби, що пожирають процесорний час. Для вирішення цієї проблеми застосовується обмеження по прив'язці до процесорів.

Див. Також[ред. | ред. код]

  • fork () - системний виклик Unix-подібних операційних систем (відповідно до стандарту POSIX)
  • Зомбі - схожі випадки витоку системних ресурсів

Примітки[ред. | ред. код]

  1. один з найбільш елегантних прикладів fork-бомби, створений Jaromil’ом