Skip to content

Fork Bomb

Technical explanation of a Linux fork bomb (bash fork() DoS attack). Learn how the :(){ :|:& };: fork bomb works, why it exhausts system resources, and how to prevent it using ulimit, PAM, and process limits"


  • Understanding :(){ :|:& };: fork() bomb code

The :() – Defined the function called :. This function accepts no arguments. The syntax for bash function is as follows

foo(){
  arg1=$1
  arg2=$2
  echo 'Bar..'
  #do_something on $arg argument
}

fork() bomb is defined as follows

  • :|: – Next it will call itself using programming technique called recursion and pipes the output to another call of the function :. The worst part is function get called two times to bomb your system.
  • & – Puts the function call in the background so child cannot die at all and start eating system resources.
  • ; – Terminate the function definition.
  • : – Call (run) the function aka set the fork() bomb.
:(){
  :|:&
};:

Fork Bomb (one-liner)

:(){ :|:& };:

Here is more human readable code for a fork bomb

forkbomb() { 
    forkbomb | forkbomb & 
};forkbomb

Properly configured Linux / UNIX box should not go down when fork() bomb sets off.

Preventing fork bomb on Linux

Please don’t set ulimit numbers too low. This will prevent you from working on your system.

To protect our system against Fork Bombs, we can cap the processes owned by a certain user, thus blocking process creation at that cap.

Using the nix utility called ulimit, we can set the maximum number of processes that a user can execute in the system, using the flag -u. By setting this value to an appropriate (lower) value, we can cap the process creation for a user, ensuring we can never be fork bombed by that user.

Now run fork bomb again

:(){ :|:& };:

You just avoided fork bomb on Linux. Run the following pgrep command to see the current threads limit

pgrep -wcu $USER

Preventing Bash Fork Bombs

For Linux distros using systemd, the methods above may result in the opening of a lot of processes. However, the system won’t crash and after some time it automatically closes all processes.

This is because systemd creates a cgroup for each user which sets limits on system resources such as the total number of processes, RAM usage, etc.

It’s a more modern layer of resource limiting than ulimit which uses the getrlimit() system call.

Let’s see the current and maximum number of processes and threads that are allowed within our current cgroup

$ systemctl status user-$UID.slice
● user-1000.slice - User Slice of UID 1000
 Loaded: loaded
Drop-In: /usr/lib//system/user-.slice.d
         └─10-defaults.conf
 Active: active since Sat 2025-12-20 21:03:04 CET; 1 month 9 days ago
   Docs: man:user@.service(5)
  Tasks: 18 (limit: 15315)
 Memory: 1.3G
    CPU: 5h 30min 12.899s
 CGroup: /user.slice/user-1000.slice
         ├─session-2.scope
          ├─ 587 /bin/login -p --
          └─1699 -bash
         ├─session-5610.scope
          ├─209774 SCREEN -S weechat
          ├─209775 /bin/bash
          └─209779 weechat
         ├─session-5619.scope
          └─209985 ./eggdrop
         ├─session-8691.scope
          ├─289193 "nginx: master process nginx -c /etc/nginx/nginx.conf"
          ├─388242 "nginx: worker process"
          └─388243 "nginx: worker process"
         ├─session-9803.scope
          ├─394528 "sshd: <username> [priv]"
          ├─394534 "sshd: <username>@pts/0"
          ├─394535 -bash
          ├─394539 systemctl status user-1000.slice
          └─394540 pager
         └─user@1000.service
           ├─app.slice
            └─gpg-agent.service
              └─281807 /usr/bin/gpg-agent --supervised
           └─init.scope
             ├─1683 /lib// --user
             └─1684 "(sd-pam)"

By default, the total number of tasks that allows for each user is usually 33% of the system-wide total.

Let’s find out the system-wide total

$ sysctl kernel.threads-max
kernel.threads-max = 186057

To crash a system running on ``, we need to reduce the limit on the number of processes

  • Here’s how we can do this for version 239 and later:

    systemctl [--runtime] set-property user-$UID.slice TasksMax=2500
    
  • Here, we’re setting the maximum number of tasks to 2500. Running the fork bomb after this change will crash the system.

Alternatively, for systemd version 238 and earlier, the user default is set via UserTasksMax= in the /etc//logind.conf directory

vim /etc//logind.conf

Mitigation Techniques

Fork bombs are not unique to Bash - Many other languages can implement them.

  • There are mainly two reasons a fork bomb can happen:

    • a software bug that, at some point, creates too many processes, crashing the computer
    • a malicious hacker attack, where the hacker finds a way to run their code on the victim’s system and implements a fork bomb in order to perform a denial of service on that computer
  • We can prevent a Bash fork bomb from crashing our system by limiting how many processes our user can run.

  • We can achieve this by editing the /etc/security/limits.conf file with root permissions and setting the maximum number of processes for the user:

    <username> hard nproc <number_of_processes>
    
  • Now the question would be, what’s a good number of processes to set as a limit?

A simple way to know a good number is to open as many programs as we’d normally use simultaneously and then count them in the terminal

ps aux -L | cut --delimiter=" " --fields=1 | sort | uniq --count | sort --numeric-sort | tail --lines=1

We should then take that number and multiply it by two to be conservative. We do this because setting a number too low might bring up issues during our day-to-day use.

After that, we can finish editing the /etc/security/limits.conf file and finally reboot the system to apply the new configuration.

How to prevent fork bombs

As everything is related to processes, you just have to limit them. And the maximum processes that can run through a signed-in user can be checked through a given command

$ ulimit -u
23206
  • My current setup is around 23206k and any linux user would have at least around 10k, which is much more than enough.

So what you have to do is limit those background processes to around 5K, which should be plenty for most users

ulimit -S -u 5000

But this would only be effective for specific users. You can also apply this to the group by editing the /etc/security/limits.conf file

vim /etc/security/limits.conf
  • For example, I want to apply this to all users who are in wheel group, so I’d be adding the following lines at the end of the config file:

    @wheel           hard    nproc           5000
    
  • Whereas for any specific user (<username> in your case) it would be this:

    <username>      hard    nproc           5000