How does this other version of the bash fork bomb work?

你离开我真会死。 提交于 2020-01-24 06:44:50

问题


I get the general idea of how this common version

:(){ :|:& };:

of the bash fork bomb works.

However, I've seen another version (for bash in particular)

#!/bin/bash
$0 &
$0 &

on the Wikipedia fork bomb article and in an SO answer to a closed duplicate of the original fork bomb question I mentioned above.

I'm looking for an explanation of how the second (perhaps less common) version of the fork bomb works. I've commented the code below with my current understanding of what it does, but I don't really get how it achieves infinite recursion in the way that the other version of the bash fork bomb does (probably due to my poor understanding of bash processes and backgrounding).

#!/bin/bash    # Specifies the location of the executable
               # to use in executing this script.
$0 &           # Duplicates (executes a new instance
               # of) the current running process ('$0')
               # (which would be the invocation of bash used
               # to start running the script, right?)
               # and background it ('&').
$0 &           # Do the same as above, where $0 would be
               # equivalent to the initial call to bash
               # used to start the script, right? Or, would
               # it be the backgrounded call to bash from the
               # second line? I'm leaning towards the former.

EDIT: My revised understanding of the script (at least at the level of abstraction I'm worried about at the moment) is below in the form of commented code. I've left my original commented code up for future viewers who might have the same initial misunderstandings I had. Assume the script lives in bomb.sh.

#!/bin/bash    # Script will execute using /bin/bash executable.
$0 &           # The current process (P) will spawn a child process (C1)
               # by invoking the command that spawned P
               # (/bin/bash ./bomb.sh). This makes the script recursive.
               # & allows processes to run in the background
               # (allowing process death and avoiding a potential
               # process limit).
$0 &           # Process P spawns a second child process (C2), also 
               # in the background, which gives us the exponential growth
               # (in base 2) that we want per level of recursion.

回答1:


If you break this bomb down a little it might make more sense. Change this to:

#!/bin/bash
$0

This bomb will spawn a new copy of the shell script over and over again:

$ ps auxw | grep pts/2
sarnold   2410  0.0  0.1  24840  6340 pts/2    Ss   Nov17   0:01 bash
sarnold  17280  0.0  0.0  12296  1600 pts/2    S+   18:01   0:00 /bin/bash ./bomb.sh
sarnold  17281  0.0  0.0  12296  1600 pts/2    S+   18:01   0:00 /bin/bash ./bomb.sh
sarnold  17282  0.0  0.0  12296  1600 pts/2    S+   18:01   0:00 /bin/bash ./bomb.sh
sarnold  17283  0.0  0.0  12296  1596 pts/2    S+   18:01   0:00 /bin/bash ./bomb.sh
sarnold  17284  0.0  0.0  12296  1600 pts/2    S+   18:01   0:00 /bin/bash ./bomb.sh
...
$ ps auxw | grep pts/2 | wc -l
2077

Each old one is essentially "dead" -- waiting to reap the exit status from the executed child. Of course, that won't happen until one of the executed children finally cannot execute due to process limits. (Which incidentally reminds me that perhaps setting an nproc rlimit would be a good idea before playing much further.)

So this process tree looks like this:

1
 2
  3
   4
    5
     6

If you add the & to the end of the command, you'll see that older ones can eventually get scheduled and die. New ones form just as rapidly though, so this causes pretty significant churn and helps reduce the chance that it'll just end when the maximum number of processes have been spawned. The tree will look more like this:

1
 2
  3

    5
     6

       8

Adding the second $0 & line will cause the tree to look a little different:

           1
        2     3
      4   5 6   7

Except it probably won't be this nice -- the second process might start the third, rather than the first one starting the third. It'll probably look mighty chaotic.

Each "layer" will double the size of the previous layer, on the whole, but execve(2) can only be called so often -- the trick is that this bomb will probably force far more process context switches than the simpler bombs, and all those TLB flushes are going to significantly impact the performance of the system. Because parents will be essentially randomly dying off after executing both children, init(8) will have far more processes re-parented. All this will increase the number of signals sent to init(8) to clean up, which would make it harder for an admin to log in and fix the problem.




回答2:


When you run $0 &, Bash runs a new process in the background that runs this script. You start by doing it twice. Then each one of those scripts does it twice, so the second round of instances starts four instances. The next round starts eight, then 16, then 32, and so on.




回答3:


$0 is a variable containing the very first part of the command that was used to call this script: The name and location of the script. If for example the command that you used to call the script is /home/user/bin/bomb foo bar, $0 will contain /home/user/bin/bomb. So $0 & means run this same script in the background. Since it is in the script twice, it will spawn 2 children. Each of the children will spawn 2 more children, and so on, exponentially.



来源:https://stackoverflow.com/questions/8394435/how-does-this-other-version-of-the-bash-fork-bomb-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!