Hacker News new | past | comments | ask | show | jobs | submit login
Simple kernel attack: Eat 100% CPU, works under guest, no way to protect (lkml.org)
94 points by tableton on Nov 25, 2010 | hide | past | web | favorite | 46 comments

Has anybody launched this in a VM under Xen and/or EC2 to see if AWS is vulnerable? If this can mangle the Dom0 over a paravirt DomU, this would be awfully interesting.

/me off to test...

update: Would be nastier if it forked cpux2 times or something at startup. My test server is running fine for 15 minutes with it active. A bit slow, but still responsive and accepting new SSH connections. Server is Centos 5.5 with 2.6.18-194.26.1.el5

Proc net unix seems stable as below, maybe slowly growing now.

[root@xenpig net]# cat /proc/net/unix | wc -l


I have kill -9 that process several times though, and it ain't dying, so that is an issue.

You can cap the amount of CPU utilization for VMs, so I don't think you could bring the server to a crawl, only the VM.

I ran it on a domU and it seemed to have no affect at all on the host machine (Xen 3.3)

As for other virtualization products, I tried in inside an OpenVZ setup (Proxmox 1.6). A container almost took down the hardware node. It was very slow, although responsive. "vzctl stop" timed out. Just a reboot brought back that machine. Therefore, I am living under the impression that any container based virtualization technology is vulnerable due to the usage of the same kernel for all the available virtual machines.

Proxmox ran inside a VirtualBox instance. All the allocated memory to the virtual machine was taken by the exploit. Even more, after rebooting the VirtualBox machine, it leaked the whole memory used by the affected Proxmox. The only way I could get it back was to stop the VirtualBox machine.

Apparently someone used this on the lkml.org web server.

I would call it an attack if you can inject it into someone's else machine build it and run it as guest (or upload it as a binary and run it).

Writing a program which eats all available CPU and other resources it is not a big deal, is it?

There is no good description of the program, but if the program is unkillable, it's an attack. root should be able to kill stuff, if root can't, that's a big deal.

The big thing is that it's unkillable (even by root) because its chewing CPU while in running kernel code.

There are other ways of gaining remote access. This is a pretty well-constructed local DoS attack you can run (without root access, I think!).

Attacks can take many forms, most new attacks are single components that one would combine to perform a real-world attack.

Here, you would combine some method of gaining remote access (maybe a webserver hole you can drop a shell with) with this and get an excellent remote DoS attack.

One really easy way of getting remote access is to ask for it. Local exploits and DoS attacks are important not just because other exploits may let you run code remotely: there are many situations in which computers are not single-user devices. At my university anyone can remotely log in to any of the machines used as lab workstations and there are numerous shared fileservers you can log in to as well. People also still routinely purchase "shell accounts" on shared hosting providers.

virtual server instances on a machine with a compromised instance. cpu eater becomes non-trivial.

You linked to a thread that is not the original one.

The problem was originally reported 2 days earlier by Vegard Nossum: http://thread.gmane.org/gmane.linux.kernel/1067149

The problem reported there is slightly different; the program linked in the OP operates recursively, building a larger and larger graph of 'in flight' FDs, while the earlier report simply allocates a bunch of pairs and sends FDs to them. The earlier report is apparently fixable by triggering the GC in this case (as mentioned in the lkml followup), but that fix does not address the exploit in the OP.

The one I linked to is exactly the same as the one in this HN submission (on an alternate mailing list archive site, because the one used in the submission seemed to have failed under the load at the time).

By installing Flash player?

You made me laugh, but HN is no place for humor.


This made me laugh too actually :-)

Not informed enough to say if the code is as interesting as the title implies. Hope someone comments to enlighten me, shall upvote if so!

You can send a file descriptor over a socket between two processes. (Google "SCM_RIGHTS").

This is one place in the kernel where it employs a garbage collector (hey, they need to start somewhere ...). The reason is that there's an uncomfortable part about this API: the reader doesn't necessarily have to pick up the file descriptor it is sent. If the sender closes the fd, the kernel needs to detect that the reader didn't pick up the fd and deallocate the underlying file resource. Hence GC needed.

This code makes sure that many such fds are "in flight" over the socketpair, and by closing the socket instead of reading from it, ensures they are leaked. The GC doesn't get invoked under this particular set of circumstances so eventually you consume all system file resources. (I think even ulimit doesn't stop this).

Solution as in the follow up message is to run the GC in an extra place.

> and by closing the socket instead of reading from it, ensures they are leaked.

It does:

    create socketpair N+1
    send socketpair N over socketpair N+1
    close socketpair N
So the only ones that are ever closed are the local copy of something that was sent over another socketpair. So all of the fd's are reachable, assuming that an in-flight fd is (like a received fd) a copy of the original fd rather than a reference to it.

Seems like in-flight fds should still count against the sending process's open file limit. (So that all fds are counted against some processes open file limit).

Well, apparently the GC doesn't work too well here (the self-followup talks about a non-maskable interrupt watchdog triggering, i.e. the GC takes too long). But yes, I don't understand why this would necessarily be unsolvable.

Wait, is this run locally because I could just do :(){:|:&}; :& which is pretty effective.

Not on a competently-run (multiuser) system, which will have process limits etc in place.

Indeed. I'm wondering if the parent attack somehow bypasses open file hard limits.

Am I the only one who initially thought this was a sequence of emoticons?

I'm not sure why : has been chosen as the canonical fork bomb function name, but it's more readable with something like

resurse() { recurse | recurse &}; recurse

In this example, the poor readability is a feature. Nevertheless the ":" character is bash inner function, which tells the shell to do nothing (except the arguments expansion), like pass in python. This means that you can redefine it and use it to confuse others. Most of other special characters are not functions so you are not able to redefine them that easily.

And it's usually accompanied by the adjective "elegant", which I find rather baffling.

"Cute" or "cryptic", perhaps.

Confuse the computer by making it sad?

haha yes I can see it now. Its a bash function that gets called recursively. Nice and simple, I've tested it in a few different environments, linux 2.4, linux 2.6, open bsd, solaris. All vanilla installs. Solaris is the only one I havent seen die.

For the uninitiated see the Wikipedia entry on "fork bombs"

u mind sharing what ":(){:|:&}; :&" means?

:() is a function that accepts no arguments, it calls itself (recursion) then pipes the output to another call to itself that is backgrounded, basically two calls to the function. That is the function definition, it is then called and backgrounded via :&

I am a true believer in the power of bash and despite the fact that it is not a programming language I will still try use it in that form just for fun.

What happens if you renice the process so everything else takes priority?

Probably nothing, since it happens in the kernel, not in userspace.

Isn't it possible to mitigate the problem in limiting the number of sockets an user process may open?

Despite knowing it was aimed at Linux, which I don't use, I still had to try it out to settle my curiosity: it's completely harmless on OpenBSD and Mac OS X; it does not hang either of these OS' kernels, and does not eat FDs.

BSD doesn't support SOCK_SEQPACKET on unix domain sockets. The app exits early.

Shame on you, Марк Коренберг! Releasing ready-to-use exploits harms everybody.

It doesn't harm me.

It also let's people prepare for it and create solutions. It's not a bad policy, and not releasing the exploit can in many cases be more harmful.

Exactly. Disclosure is best.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact