From a831707ab3f89c7558e3d91b63e3cbe6dce67c23 Mon Sep 17 00:00:00 2001 From: Aaron Ball Date: Thu, 15 Apr 2021 11:31:52 -0600 Subject: Convert understanding the bash fork bomb from adoc to rst This also converts all the pre references to bash code blocks for easier readbility, and rewrites a few sentences. Finally, this also removes the modeline. --- posts/understanding_the_bash_fork_bomb.adoc | 105 -------------------------- posts/understanding_the_bash_fork_bomb.rst | 110 ++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 105 deletions(-) delete mode 100644 posts/understanding_the_bash_fork_bomb.adoc create mode 100644 posts/understanding_the_bash_fork_bomb.rst diff --git a/posts/understanding_the_bash_fork_bomb.adoc b/posts/understanding_the_bash_fork_bomb.adoc deleted file mode 100644 index 83b6481..0000000 --- a/posts/understanding_the_bash_fork_bomb.adoc +++ /dev/null @@ -1,105 +0,0 @@ -Understanding the Bash Fork Bomb -================================ -:author: Aaron Ball -:email: nullspoon@iohq.net -:revdate: November 12, 2015 - - - -I suspect that most Linux users, new and old, have at some point seen the -stereotypical fork bomb, whether they knew what it was or not. - - :(){ :|:& };: - -A very cryptic statement that appears to have various forms of smiley faces in -it. But what does it do and how does it work? - - -== What is a fork bomb? - -First, let's start by describing a fork. When a process creates another -process, that's called a process fork. For example, a program needs to read -data from two log files at the same time, so the main program process forks -two children processes, each to read data from the log file into memory. While -those two processes are running, the program consistes of three running -processes: the parent and two children. - -To see this in action, a fun command to run is - - ps -ef --forest - -That command will show you a graphical representation of parent processes and -their children (and their children's children and so on). - - -A fork bomb is is a process that forks off children processes, each of which -forks off its own children processes. For example, assuming each process -creates two, the parent process would create two children processes, each of -which creates two more. The result becomes 1 -> 2 -> 4 -> 16 -> 256 -> 65536. - -The key concept that makes a fork bomb work [so deviously] is that the parent -process of any child processes won't exit until the children exit. In the case -of a fork bomb, the task of a child process is to create more children -processes, thus they never exit because there is no terminus for process -creation. - -To summarize, a fork bomb could fill up a system's process table very fast. In -the example where we created 2 new children for each process, it took 6 steps -before we hit 65536 processes, which would crash many systems. - - -== How does this fork bomb work? - - -To better understand the stereotypical bash forkbomb, let's expand it into more -human-readable code. First, the original forkbomb for easy no-scroll reference. - - :(){ :|:& };: - -Now, let's break the function apart. In bash, there are two ways to define a -function - - function some_name { - # Do stuff here - } - -and... - - some_name() { - } - -The forkbomb mentioned at the beginning of this post uses the second function -syntax. As you can see, using that syntax, it creates a function called *:*. -Now, let's expand this into a much less compressed format now, by using the -first syntax, breaking it into multiple lines, and renaming the function from -*:* to *foo* - - function foo { - foo|foo& - } - foo - - -Now that's much easier to understand. It's fairly clear now that this creates -a function called foo that calls foo, piping the output to another call of foo -that's backgrounded so it can continue (the &), then finishes the function -definition and calls foo to start things off. - -As mentioned, once the function is called, it calls _foo|foo&_, which -basically executes foo, piping the function's output (nothing) to a new -instance of the foo function, and backgrounding that process. However, within -the foo function, it calls foo again, which inside, has two more calls to foo, -etc. Effectively, it recursively creates two children functions that never -close because they each create two children functions that never close because -they each create two children functions... Get the idea? - -Ironically enough, despite how impacting this function can be, it actually does -relatively little work except to create new instances of the function. Kind of -devious that a function that does no real processing can bury a system with -load. - - -[role="datelastedit"] -Last edited: {revdate} - -// vim: set syntax=asciidoc: diff --git a/posts/understanding_the_bash_fork_bomb.rst b/posts/understanding_the_bash_fork_bomb.rst new file mode 100644 index 0000000..56f7015 --- /dev/null +++ b/posts/understanding_the_bash_fork_bomb.rst @@ -0,0 +1,110 @@ +Understanding the Bash Fork Bomb +================================ + +I suspect that most Linux users, new and old, have at some point seen the +stereotypical fork bomb, whether they knew what it was or not. + +.. code-block:: sh + + :(){ :|:& };: + +A very cryptic statement that appears to have various forms of smiley faces in +it. But what does it do and how does it work? + + +What is a fork bomb? +-------------------- + +First, let's start by describing a fork. When a process creates another +process, that's called a process fork. For example, a program needs to read +data from two log files at the same time, so the main program process forks +two children processes, each to read data from the log file into memory. While +those two processes are running, the program consistes of three running +processes: the parent and two children. + +To see this in action, a fun command to run is + +.. code-block:: sh + + ps -ef --forest + +That command will show you a graphical representation of parent processes and +their children (and their children's children and so on). + +A fork bomb is is a process that forks off children processes, each of which +forks off its own children processes. For example, assuming each process +creates two, the parent process would create two children processes, each of +which creates two more. The result becomes 1 -> 2 -> 4 -> 16 -> 256 -> 65536. + +The key concept that makes a fork bomb work [so deviously] is that the parent +process of any child processes won't exit until the children exit. In the case +of a fork bomb, the task of a child process is to create more children +processes, thus they never exit because there is no terminus for process +creation. + +To summarize, a fork bomb could fill up a system's process table very fast. In +the example where we created 2 new children for each process, it took 6 steps +before we hit 65536 processes, which would crash many systems. + + +How does this fork bomb work? +----------------------------- + +To better understand the stereotypical bash forkbomb, let's expand it into more +human-readable code. First, the original forkbomb for easy no-scroll reference. + +.. code-block:: sh + + :(){ :|:& };: + +Now, let's break the function apart. In bash, there are two ways to define a +function + +.. code-block:: sh + + function some_name { + # Do stuff here + } + +and... + +.. code-block:: sh + + some_name() { + # Do stuff here + } + +The forkbomb mentioned at the beginning of this post uses the second function +syntax. With that understanding, as you can see, using that syntax, it creates +a function called ``:``. Now, let's expand this into a much less compressed +format now by breaking it into multiple lines and renaming the function from +``:`` to ``foo`` + +.. code-block:: sh + + foo() { + foo|foo& + } + foo + + +Now that's much easier to understand. It's fairly clear now that this defines a +function called ``foo`` that calls iteself (recursing), piping the output of +the recursive call to another call of itself, which is then backgrounded so it +can continue (the ``&``). Finally, the function is called to initiate the +cascade. + +As mentioned, once the function is called, it calls ``foo|foo&``, which +basically executes foo, piping the function's output (nothing) to a new +instance of the foo function, and backgrounding that process. However, within +the foo function, it calls foo again, which inside, has two more calls to foo, +etc. Effectively, it recursively creates two children functions that never +close because they each create two children functions that never close because +they each create two children functions... Get the idea? + +Ironically enough, despite how impacting this function can be, it actually does +relatively little work except to create new instances of the function. The end +result however is to fully saturate the process table, leaving no pids +remaining to start new processes, so you can't even execute ``kill`` to stop +it. Kind of devious that a function that does no real processing can bury a +system with load trying to manage all of that nothing. -- cgit v1.2.3