Search This Blog

Thursday, December 30, 2010

Fork Bombs


Once a successful fork bomb is active in a computer system, one may have to reboot it to resume its normal operation. Stopping a fork bomb requires destroying all running copies of it. Trying to use a program to kill the rogue processes normally requires creating another process — a difficult or impossible task if the host machine has no empty slots in its process table, or no space in its memory structures. Furthermore, as the processes of the bomb are terminated (for example, by using the kill(8) command), process slots become free and the remaining fork bomb threads can continue reproducing again, either because there are multiple CPU cores active in the system, and/or because the scheduler moved control away from kill(8) due to the time slice being used up.
On a Microsoft Windows operating system, a fork bomb can be defused by the user's logging out of his/her computer session.
However, in practice, system administrators can suppress some of these fork bombs relatively easily. Consider the shell fork bomb shown below:
:(){ :|: & };:
One important "feature" in this computer code means that a fork bomb process which can no longer fork doesn't stick around, but rather exits. If we try often enough, eventually we start a new do-nothing process. Each new do-nothing process we run reduces the number of rampant "fork bomb" processes by one, until eventually all of them can be eradicated. At this point the do-nothing processes can exit. The following short Z Shell code will typically get rid of the above fork bomb in about a minute[citation needed]:
while (sleep 100 &!) do; done
Alternatively, stopping (“freezing”) the bomb's processes can be used so that a subsequent kill/killall can terminate them without any of the parts re-replicating due to newly available process slots:
killall -STOP processWithBombName
killall -KILL processWithBombName
When a system is low on free PIDs (in Linux the maximum number of pids can be obtained from /proc/sys/kernel/pid_max), defusing a fork bomb becomes more difficult:
$ killall -9 processWithBombName
bash: fork: Cannot allocate memory
In this case, defusing the fork bomb is only possible if you have at least one open shell. You may not fork any process, but you can execve() any program from the current shell. You have only one try, so choose with care. A couple of the best choices are python and busybox, for example:
bash$ exec busybox sh
$ killall -9 processWithBombName
killall in busybox is an internal command and does not depend on fork().
Why not exec killall -9 directly from the shell? Because killall is not atomic and doesn't hold locks on the process list, so by the time it finishes the fork bomb will advance some generations ahead. So you need to launch a couple of killall processes, for example:
while :; do killall -9 processWithBombName; done

No comments:

Post a Comment