Fork Bomb
en.wikipedia.org
en.wikipedia.org
Like many bad ideas, it starts with an innocent question: "What happens if we recursively fork?"
Five minutes and a couple of C compiles later, we're sitting at the DEC printing console watching the system panic. The sysadmin comes running in a minute later.
"What did you THINK would happen?"
We explained that we didn't know, and we wanted to find out. He rebooted the system, fixed up a couple of busted inodes with ncheck and clri and so forth (this, children, was in the days before fsck...) and went back to his meeting, grumbling "... (inaudible) interns..."
And that's when I got seriously interested in how kernels worked.
Well, I guess my dad took that as a challenge, and doing something using some weird recursive assembly and trying to reclaim some extra RAM by using the ROM chip (not 100% sure what he was trying to do), he managed to completely brick the machine, permanently breaking it.
Apparently they were pretty pissed at him, but he rebutted with "Well, you guys told me that I couldn't break it just by coding!" I guess they begrudgingly agreed and never tried to make him pay for it or anything like that, but they did announce to the class the next day that apparently you can break the machines, and to not do anything too clever without a professor looking at it.
~ $ gcc fork-bomb.c
~ $ ./a.out
I saw that it did indeed crash my lab machine, and when it rebooted I went on with my life.Our CS lab had a central server which served a lot of important functions and also was the terminal server you could SSH into when working from your dorm. All of these had shared home directories.
Late one night working from my dorm before a big project was due I ran:
project $ gcc project.c
project $ ~/a.out # note the '~'
And forkbombed the central server. A lot of people were pretty mad at me.Lessons learned:
* People should not be logging into the central server to do their work, or it should at least have nproc limits
* Always name your executables (gcc foo.c -o foo)
* Don't leave bombs lying around
I'd say that's probably good advice regardless of your profession ;)
I believe that nproc limits are only useful against accidents. In particular the following shell script is very good at taking out systems no matter what limits you set.
#!/bin/sh
perl -e '1 while push @big, 1` &
$0 &
$0
If you prevent it from taking out all of the process spots, it still is going to wipe out your memory. If you set paranoid enough limits on both memory and process spots, the system is going to be unusable for normal use cases. eval $(echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode)
Classic stuff. So I'll just remove the eval and subshell and let echo through to uudecode so I can see what this mess will do.. aaaaaaaand there goes my system.I'd neglected to see the backquoted strings in the mess. This one had some layers!
This was going to take a few days to run, largely because it was forking 10-20 times for every IP address, most of the lookups themselves were fairly quick (though some weren't). I explained to him that forks are fairly expensive operations, and every line in his shell script was 1+ forks.
I thought this would be an easy win, I picked up a multi-threaded DNS lookup tool and showed him that it could look up a thousand addresses in < a second. "Oh, so I can just replace the "nslookup" with this other program in my script?"
I explained that he would need to make a file with all the IP addresses he needed to look up, I'd run the program on a server at our data center (to not clog the office T1), and then I'd give him back a file containing "address,name".
"Oh... So I'd have to correlate each address to a name myself? I can't do that, I need to run this script." In my head I said "You're the DBA, how can you NOT correlate this data?"
I worked in a hospital years ago as an IT Tech. I realized one day the printers were not on a separate VLAN. The network guy didn’t seem to care so I wrote a short telnet script to submit a 1000 page (blank) print job to his office printer, flash all the lights and change the display to PC LOAD LETTER. I hit enter and 5 min later sure enough there was a ticket in my queue to diagnose the printer. I killed the script, set the lights to normal and went to his office. Never was able to replicate his complaint...
Apparently, so did Reuters.
The other fun trick was finding someone who had left xhost+ open and while a boss was at their desk, popping open NSFW pictures on their screen in an xv window.
Did this ever end up actually getting someone in trouble? I've worked at a few places where it certainly would.
How far back would this be? The people I know who lived through the '90s don't seem to agree…
A friend and I arrived at changing their .plan or .project to say "I really need to learn to log out when I leave the computer lab." then log them out and amuse ourselves with how long it would take them or their friends to notice.
What I should have done was note the account name and check in from time to time to see how long it took, but I apparently wasn't that forward-looking.
However I do believe I knew another person who put a sleep and a giant banner in .profile to drive the point home.
echo "ponysay remember to log out" >> .profile
or maybe: echo "ponythink i should always log out" >> .profile
(or the lesser cowsay)They had a similar security issue with /dev/audio where one could "bug" a remote machine and play the audio locally.
In terms of audio there was a desk analyst on the MBS trading desk who wrote a script that would play a clip of someone in a thick accent screaming 'You are a stupid man!' on the targeted machine. The traders and analysts did it to each other for a while. When that got boring and they modified the script to play it on all the machines on the MBS trdaing desk, repeatedly. When the head of mortgage research would stop by to speak to one of the traders, someone would quite subtly run the script and every ones machine would start barking 'You are a stupid man!'
Weirdly it never occurred to us to use the microphone.
it is not funny.
Snark aside, I agree. Accumulating 'sleep 1' in their login-scripts is more fun anyway.
I got downvoted. I think my colleague also reads HN. :p
1) Change all their desktop icons to target shutdown.exe (I had a script on the shared drive for this).
2) Screenshot the desktop, rotate it 180 in paint then set it to the desktop background.
3) Select all the icons on their destop and hide them.
4) Close all the open applications.
5) Hide the task bar.
6) Hit CTRL+ALT+Up Arrow to enter “projector mode” and get the inverted desktop screenshot back to “normal” but completely screwing up mouse movement.
7) Turn the monitor off.
8) Unplug the keyboard and mouse.
Always fun to watch them struggle through the process in reverse just to end up shutting down when trying to open outlook.
One of the Linux guys had a script that detected changes to his wallpaper, set it back to the previous one and insulted the person who attempted to change it.
When my workstation locked up, I stood up and heard a commotion coming from his cube. He was on the phone with one of our sysadmins, desperately trying to kill the processes via his non-functional terminal. I asked for the phone, and told the sysadmin (who still had a functioning terminal) to rename "sh" to something else for a second.
Boom! In just a few seconds all of the processes died out.
I said "Thanks", handed the phone back and went back to my cube while he just stared at me slack-jawed.
exec mv /bin/sh /bin/sh.oldDidn't HP-UX have ulimits configurable per-user?
In most situations this would have been OK, but it was running as root on a production server. So I could not (for example) kill all my processes with kill -9 -1 because that would have killed the machine.
So the pid of my errant program was counting up quite fast. I tried finding it in the output of ps then running while !kill $pid; do :; done for a slightly bigger $pid, hoping that my program would be killed when its pid reached $pid - nope, it won the race, and forked right past the kill loop. I tried rewriting the kill loop in C and the problem program still won the race.
In the end I needed to run several copies of the C kill loop on consecutive pids in order to kill the problem program as it forked through the kill zone. The collateral damage was only a few ftp login attempts...
Later, he came out of the machine room and asked me to look at something. There were a whole bunch of stalled batch jobs and two jobs sleeping in the active slots. I calmed him down and showed him the equivalent of "kill -9" and promised never to do it again.
foo() {
echo "$1" | foo
}
Then called foo later. The 2nd occurrence of foo was a typo for something with a very similar name. Took me a few reboots before I realized this.I find this a bit more interesting than the cited shell example because it does not involve the & token. Just pipes.
My favorite bit was he showed me the code, I saw the problem and rather than telling him how to flood my mailbox properly (because really, who would?) I just said, "You don't want to do that..." and walked away.
- Boss asks me to write a script to check X resource
- Script is done and takes around 30 seconds to run
- Boss neglected to tell me script was schedule to run once a minute
- As load increased, script started to take more than 60 seconds to run
- Since we are running script every 60 seconds, we start having multiple copies of the script
- Server goes down
#funtimes
for word in `cat /usr/share/dict`; do whois "$word.com"; done
and shortly got a phone call from Network Solutions, "What the hell are you guys doing? You're hammering us?"No such luck for the first guy I knew who fork-bombed himself on a Sequent.
I called them up and explained that it was an accident, but also asked why they did not enforce quotas on user accounts to prevent such things. They thanked me and re-enabled my account right away.
Another one was the malloc() bomb (sometimes combining with the fork-bomb to be the malloc-fork-bomb(). On some modern OSes, you have to actually initialize memory to something other than zeroes and keep a pointer to them to prevent aggressive compression and heap compaction.
Finally, running John the Ripper when they still ran NIS and getting the passwords of 26 lecturers and professors in 30 seconds by simply taking the output from getent passwd.
PS: Back in the day, before people lost their minds and over-criminalize nothingburgers, I almost got Aaron Schwartz'ed when I setup a web proxy in the computer lab to access some payware documentation off-campus that was IP locked. Thankfully, they use Postgres instead of Redwood Shores'-ware now.
Luckily the lazy sysadmin takes a lifetime to notice and correct the issue:)
But one semester, the OS class added a new first assignment: write a shell. It took about a day or two, but after the second or third accidental fork bomb, a generous per-user process limit was imposed.
while true
try:
os.fork()
except Exception as e:
continue $ cat nice.sh
rm -rf $HOME
$
In the end the user trusts the program/script to not be harmful. That's why we have the browser platform (which shields programs (aka web apps) from the local file system) and advanced permission management in the popular app stores ("this app wants to access your local file system").Don't tell browsers that. Javascript hooks for everything, from your clipboard (hope you don't use a password manager), to Bluetooth (oh you like screaming in your music?), and even your USB devices (is your $HOME mounted over USB?)...
I found some ascii art of the trollface (https://i.kym-cdn.com/entries/icons/original/000/000/091/Tro...) and saved it to a file, then wrote a script that would find user $1 and infinitely "talk" trollfaces at them, making their terminal completely unusable. Then I'd run it against my friends when we were working in the computer lab :)
Shared Unix systems are rife with prank opportunities
My favorite was `cat /dev/dsp > ssh otherbox 'cat > /dev/dsp'`
I could talk into my laptop's microphone and it would play over the speakers on my classmate's workstation.
An interesting technique i've heard is to do: ``` while true; do sleep 10m &; done ``` The goal is to exhaust the PID space, which will cause forking to fail and eventually bring the system back under control.
-- No warranty, may break the universe and eat your children --
:(){:&;:};:&
int*f(int n){char*p,*r=malloc(n);for(p=r;r&&n--;)*p++=n;return r;}int main(){int i=10;sleep(1);do printf("&%1d",i[f(1<<20)]&1),fork();while(--i);main();}
Here's others that aren't mine in a zillion languages:Unfortunately the script was called with the wrong arguments, leading to the cluster submitting jobs recursively back to itself until the entire thing went down.
Good times.
With limited computers in the computer lab this was especially efficient if you set them to open, spawn, and replicate on startup. The old systems could barely handle it and would just error out and the cycle continued.
int main() {
printf("choo");
fork();
}I think it was like this: Program Bomb uses crt,graph; Var Graphics,Mode: smallint; begin Graphics:=Detect; Mode:=detectMode; while(1!=0) InitGraph(Graphics, Mode,'');
It killed an old PC with Windows 2000
Example: JavaScript vs "%0|%0"
There is an additional subtlety in that : is the null command, which is being redefined.
for {
go main()
}Also, when the OOM-killer gets around to killing your Go program, it'll take the whole thing down in the single OS process, rather than a fork bomb where you have to get all the processes.
Writing a true Go forkbomb is actually a bit harder, because as with many such runtimes designed from top-to-bottom around the idea of having a lot of threads, "fork" is not readily available. It's generally not meaningful to fork a highly multi-threaded program. The closest you could get would be to repeatedly execute /proc/self/exe over and over, which will come close, but probably still somewhat slower.
fork while forkEDIT: thinking about this further, I don't think that would be right either, as state from the process won't come over with the fork. So maybe there isn't a way?