Well, if it's a fork bomb ye be wantin, it's a fork bomb ye be getting.
But before we detonate a couple, what the heck is a fork bomb, what does it do, why
is it called that, and how does it work?
Long story short, it's an 11 character program that anyone can enter into any system - Windows,
Linux, or Mac - that has the bash shell.
It will crash or render that computer inoperable within moments, even if you're not an administrator
on the machine.
Basically, you can ruin any system that hasn't had specific limits and protections configured
in advance, and since they're not the default, almost no one does so.
Once I demonstrate the carnage a fork bomb can cause, I'll also tell you how to protect
your own systems, all today in Dave's Garage.
[Intro] Hey, I'm Dave, welcome to my shop!
I'm Dave Plummer, a retired operating systems engineer going back to the MS-DOS and Windows
95 days, and fork bombs are actually not a new phenomenon.
In fact, defusing them on a PDP-11 running Unix was one my lab assignments back in college.
Which, suffice to say, was not exactly recent.
What's a fork bomb look like?
Well, here it is.
11 characters, mostly punctuation, that will cripple most any computer.
You just enter them into the command line and boom, boom, out go the lights.
Do not attempt this on any system that you do not own, and don't do it anywhere that
data loss could be a problem.
I literally hooped the disk structure of my own machine just yesterday experimenting with
a fork bomb while preparing for this episode, so it's no joke.
It can't really be that easy, can it?
11 characters?
No admin rights?
Especially if it's been known about for decades?
Well, there's only one way to find out.
Let's head to the desktop and drop a fork bomb into the gears of both a Linux system
and a Windows system to see how they fare.
I also tested the Mac - more on that later.
I'll be running Windows 11 and Ubuntu 20 on the same machine as peers of the same hypervisor.
Without going into the weeds too far on the details, that means both operating systems
are the real deal - each has access to the real hardware through the hypervisor and neither
is a Virtual Machine.
The results you see here today are the same you would get on a bare metal install of either
operating system.
Here you can see the magic 11 characters.
They don't look like much - sort of a nonsense C program if anything.
And yet, watch what happens if I type or paste those characters into the Linux command shell:
Once I press enter, notice how the CPU usage in Task Manager begins to spike.
This is a 32-core Threadripper cranking away on all 64 threads, and yet it locks up almost
immediately.
I can no longer type into the active console window and it has stopped responding to new
ssh logins, so I'm effectively at a dead end.
If we cycle over to the instance of htop that I started in advance, it's being given enough
cycles to repaint perhaps once every 20 seconds, but when it does, we can see that the cores
are all pegged to 100%.
Linux is now hooped, and I don't know an elegant way out.
The best solution it to use Windows to ask the hypervisor to reset Linux for me, and
I can do that with the wsl -shutdown command.
A minute or two later and once the Linux subsystem has restarted, all is back to normal.
Of course, any unsaved work was lost since there was no way to interact with the machine.
This begs a few questions, I think.
First, how can Windows Task Manager report on Linux's CPU use?
Because it's just that good?
Perhaps, but what it's really reporting is the hardware CPU use at the hypervisor level.
Normally Windows would only report on its own CPU usage, not that of other hypervisor
clients, but I'm guessing special support has been added to Task Manager to somehow
get that hardware information from the hypervisor itself.
The next question is would Windows fare any better?
There's only one way to find out, of course.
And you might rightly ask, "But Dave, this requires bash and Windows doesn't include
bash!".
That much is true, but bash is widely and freely available.
I've even got two different variants on my machine, one being the Git bash shell and
the other being the Cygwin bash shell.
I've pre-tested both and the results are the same regardless of which bash you use: total
digital carnage.
I simply type bash to launch the shell, and I get the bash prompt where I can now enter
the fork bomb expression.
I'll copy and paste it because that's easier, and as soon as I press enter every CPU core
jumps to 100% usage.
At this point I've lost the ability to type into the bash prompt, but it appears that
I can go to another process, like CMD, and execute commands from there, which is promising.
I first tried using the taskkill command to try to terminate all of the bash instances,
but I had little luck.
I decided to stop and save the video beforehand, but I ultimately used Task Manager's recursive
kill feature on the CMD instance itself.
I added that feature decades ago at the request of our VP, Jim Allchin, and I'm glad he asked.
On the Mac it simply locked up as a spinning color wheel mouse that I could not move and
then, a minute or two later, I got a pink screen reboot.
Of the three operating systems I tested this on, task manager is the only way I was able
to fully recover any of them.
Perhaps you naturally wouldn't think of Windows as being the most resilient of the three,
but here we are.
The Mac was clearly unrecoverable, but if you have suggestions on how I could have recovered
the Linux system, please let me know in the comments.
I could not get a new console that would allow me to do anything productive, nor could I
ssh into it, but perhaps using the existing htop instance there was a way.
Let me know!
Now that we've seen the problems a fork bomb can cause, why is it called a fork bomb and
how does it work?
Let's take a look at the expression.
It doesn't really matter if you understand this next little part, but I want to explain
it for the truly curious.
It looks a little like a C program, as I alluded to before, but that's because the bash script
interpreter uses a very C-like syntax.
What it's doing, then, is defining a function called A. So, A takes no parameters, and hence
the empty parenthesis that comes next.
In between the curly braces is the function code itself.
The first thing we find is the latter A, which means it's calling A. So a function that calls
itself - that's just recursive.
But the important part is what comes next, after the pipe symbol: another A, but this
one followed by the ampersand, which indicates it should be spun off as a parallel process.
So the function does something critically important to the whole thing: it calls itself
twice in parallel.
Next we find a semicolon, which separates two statements.
In this case, it separates our function definition from what comes next: we simple call A one
time.
So this set of 11 characters defines a function and then calls it.
If we were to write this more simply, we could write it as follows: a function name fork
that calls itself and then pipes its output to a newly launched copy of itself.
Once the function is defined on those first three lines, the fork call on line 4 lights
the fuse.
Any time the function is called it causes two more to be created before it exits.
And so, each iteration causes the number of processes to double, and this exponential
growth overwhelms the system resources no matter how much CPU or RAM you have.
It might take a second longer, but the result is the same, as we saw: a largely useless
system.
This whole process reminds me of what happens when a nuclear fission reaction reaches critical
mass: enough of the neutrons released ultimately collide with another particle and release
MORE than one neutron, one average.
As a result, you get the famous chain reaction that causes a runaway growth in neutron production.
Only in our case, instead of a cascade of neutrons, it's processes.
The original fork bombs back in the 60s and 70s were known as rabbits, presumably for
the fast rate at which they reproduced.
Modern operating systems like Linux and Windows use a copy-on-write scheme for memory management,
which means that when multiple memory pages that are truly duplicates of one another,
only a single copy is kept and then each process gets a reference to that page.
It's only if a page is modified, making it different than all the others, that a second
copy is made.
As a result fork bombs are not generally demanding of a lot of memory: instead, they hog the
CPU.
They do this through two primary mechanisms: through the sheer amount of CPU time taken
by the act of creating new processes as fast as it can, and by saturating the process table
with so many processes that each process gets only a tiny slice of CPU time.
Obviously by now it should go without saying, but do not do this on any machine you do not
entirely own and control.
Running it on someone else's machine is really just digital vandalism.
It's a denial of service attack and you would be entirely responsible for the outcome.
Preventing such attacks is relatively straightforward on Linux.
There is a command called ulimit, and if we run it with the -u parameter it will tell
us how many new child processes are allowed for a user.
On my Mac, its about 10,000.
On Linux, it's over 100,000.
Either way, that's a sufficiently high limit that malicious actors can disrupt the system.
The most basic protection is to use ulimit -u to limit each user to the actual number
of processes you believe to be reasonable.
I just checked the Mac, since it had the lowest limit to begin with, and I have about 600
processes active right now.
Perhaps 2500 would be a reasonable compromise.
Let's try it and see if it saves the system.
First I'll verify the old limit, which was 10666.
Next I'll use the ulimit command to change that number to 2500 and then run the command
a final third time to verify that the change stuck.
Next, I'll trigger a fork bomb.
The system is clearly impacted, but this 20-core machine only shoots up to about 70% total
usage, and this means there are enough CPU cycles to allow me, as the sysadmin, to intervene.
I can bring up another shell and then use the killall command to terminate all zsh processes.
It's zsh instead of bash because zsh is actually the default shell on MacOS now, but they're
so similar that they behave the same with a fork bomb.
The same approach can be used on Linux as well.
The only compromise is that you are of course limiting all users to whatever settings you
impose.
For the more advanced Linux user, check out cgroups, which would allow you much more granular
control of such limits and who they impact.
Under Windows, it's more complicated.
The plumbing is all there, it's just not exposed in a helpful way.
In fact, I know it can be done because I did it - I limited the system to some VERY small
set of processes for parts of Windows Activation so that if a crack did emerge, the system
that resulted wouldn't be very useful.
I did it all with standard APIs but as to how I did it, discretion is the better part
of valor so I have to leave that one to the viewer as an exercise.
In summary, then, a fork bomb is a type of denial of service attack in which a process
repeatedly replicates itself, creating a large number of child processes that overwhelm the
system and cause it to become unusable to crash.
In my testing only Windows could actually survive a fork bomb but ironically, it is
also the only one of the major three that I could not find a way to proactively protect.
If along the way you found today's episode to be any combination of entertaining or informative,
I'd be honored if you'd consider leaving it a like and subscribing to my channel.
If you have any interest in matters related to Autism, Asperger's, or ASD, please check
out my book on Amazon, Secrets of the Autistic Millionaire.
It's got nothing to do with money and everything to do with living a successful life on the
spectrum.
It's everything I know now that I wish I'd known back then.
Remember I'm mostly in this for the subs and likes, so please be sure to leave me one of
each before you go today.
In the meantime, and in between time, I hope to see you next time, right here in Dave's
Garage.