I saw this command somewhere: :(){ :|:& } (fork bomb). How does it work?

This is a potentially dangerous command. Don't run it! The "trigger" is omitted from the question above, leaving only the part that sets up the function.

A fork bomb is a simple form of denial of service (DoS) named after the Unix fork(2) system call. It is a program which rapidly consumes resources by repeatedly forking copies of itself, whose children do the same, recursively. On many systems without proper resource limits, this may leave you in an irrecoverably unresponsive state.

This particular definition of a Bash fork bomb is for some reason so well-known that it's sometimes just known as "the forkbomb".

Here is the code in the most common popularized format:

:(){ :|:& };:

And again, following good conventions for readability:

#!/usr/bin/env bash
:() { 
    : | : &
}

:

This defines a function named :. The body of the function sets up a pipeline, which in Bash consists of two subshells, the stdout of the first connected to the stdin of the second by a pipe. The function (parent shell of the pipeline) backgrounds the pipeline, the function returns, and the shell terminates, leaving behind the background job. The end result is two new processes that each call : to repeat the process.

: is actually an illegal function name in most contexts (described below). Here, bomb is used instead of :, which is both portable and more readable.

bomb() {
    bomb | bomb &
}

bomb

Theoretically, anybody that has shell access to your computer can use such a technique to consume all the resources to which he/she has access. A chroot(2) won't help here. If the user's resources are unlimited then in a matter of seconds all the resources of your system (processes, virtual memory, open files, etc.) will be used, and it will probably deadlock itself. Any attempt made by the kernel to free more resources will just allow more instances of the function to be created.

As a result, the only way to protect yourself from such abuse is by limiting the maximum allowed use of resources for your users. Such resources are governed by the setrlimit(2) system call. The interface to this functionality in Bash and KornShell is the ulimit command. Your operating system may also have special configuration files to help manage these resources (for example, /etc/security/limits.conf in Debian, or /etc/login.conf in OpenBSD). Consult your documentation for details.

Why '':(){ :|:& };:'' is a bad way to define a fork bomb

This popular definition works because of an unusual combination of details that (of the shells I have to test with) only occur in Bash's non-POSIX mode, and Zsh (all emulation modes).

  1. The shell must allow defining function names beyond those required by a POSIX "Name". This immediately rules out ksh93, Bash POSIX mode, Dash, Posh (segfault on definition, Posh is an old pdksh fork that's no longer maintained), and Busybox sh.

  2. The shell must either:
    • Incorrectly resolve functions that overload special builtins ahead of the builtin itself. See Command search and execution. mksh fails (correctly) at this step, simply executing the : builtin. It is impossible to call the function even if you've successfully defined it. Bash non-POSIX mode and Zsh (even POSIX emulation) meet this criteria.

    • Provide a means of disabling the builtin. Bash and Ksh93 do. Bash fails (correctly according to its documentation). Ksh93 succeeds (incorrectly according to its documentation).
          $ bash -c 'enable -d :; type -p :'
          bash: line 0: enable: :: not dynamically loaded
          $ ksh -c 'builtin -d :; whence -v :'
          ksh: whence: :: not found
      Probably a bug:
        -d    Deletes each of the specified built-ins. **Special built-ins cannot be deleted**.
      In any event, it's irrelevant because ksh93 already failed at step 1. Now you just have an inaccessible builtin.

So in a nutshell, this forkbomb isn't very interesting. It's basically the canonical definition that's been trivially obfuscated by giving it a strange name that breaks almost everywhere. Ironic given the supposed original author's claim that one may

type in :(){ :|:& };: on any UNIX terminal

BashFAQ/059 (last edited 2013-01-08 18:58:36 by GreyCat)