Simple kernel attack: Eat 100% CPU, works under guest, no way to protect
lkml.org
lkml.org
/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
153406
I have kill -9 that process several times though, and it ain't dying, so that is an issue.
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.
Writing a program which eats all available CPU and other resources it is not a big deal, is it?
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.
The problem was originally reported 2 days earlier by Vegard Nossum: http://thread.gmane.org/gmane.linux.kernel/1067149
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.
It does:
create socketpair N+1
send socketpair N over socketpair N+1
close socketpair N
repeat
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.resurse() { recurse | recurse &}; recurse
"Cute" or "cryptic", perhaps.
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.