Thursday, August 13, 2009

Linux NULL pointer dereference due to incorrect proto_ops initializations (CVE-2009-2692)

EDIT2: Here is RedHat's official mitigation recommendation
EDIT3: Brad Spengler also wrote an exploit for this and published it. The bug triggering is based on our exploit which leaked to Brad though the private vendor-sec mailing list. He implements the personality trick Tavis and I published in June to bypass mmap_min_addr and also makes use of a feature that allows any unconfined user to gain the right to map at address zero in Redhat's default SELinux policy. He wrote a reliable shellcode for this one that should work pretty much anywhere on x86 and x86_64 machines.
EDIT4: if you use Debian or Ubuntu on your machine, I have specifically updated the kernelsec Debian/Ubuntu GrSecurity packages to protect against this bug and others.
EDIT5: Zinx wrote an ARM Android root exploit
EDIT6: Ramon de Carvalho Valle wrote a PPC/PPC64/x86_64/i386 exploit

Tavis Ormandy and myself have recently found and investigated a Linux kernel vulnerability (CVE-2009-2692). It affects all 2.4 and 2.6 kernels since 2001 on all architectures. We believe this is the public vulnerability affecting the greatest number of kernel versions.

The issue lies in how Linux deals with unavailable operations for some protocols. sock_sendpage and others don't check for NULL pointers before dereferencing operations in the ops structure. Instead the kernel relies on correct initialization of those proto_ops structures with stubs (such as sock_no_sendpage) instead of NULL pointers.

At first sight, the code in af_ipx.c looks correct and seems to initialize .sendpage properly. However, due to a bug in the SOCKOPS_WRAP macro, sock_sendpage will not be initialized. This code is very fragile and there are many other protocols where proto_ops are not correctly initialized at all (vulnerable even without the bug in SOCKOPS_WRAP), see bluetooth for instance.

So it was decided that instead of patching all those protocols and continue to rely on this very fragile code, sock_sendpage would get patched to check against NULL. This was already the way sock_splice_read and others were handled.

Since it leads to the kernel executing code at NULL, the vulnerability is as trivial as it can get to exploit (edit: that's for local privilege escalation and on Intel architectures): an attacker can just put code in the first page that will get executed with kernel privileges. Our exploit took a few minutes to adapt from a previous one:

$ ./leeches
// ------------------------------------------------------

// sendpage linux local ring0
// ----------------,
// leeches.c:Aug 11 2009
// GreetZ: LiquidK, lcamtuf, Spoonm, novocainated, asiraP, ScaryBeasts, spender, pipacs, stealth, jagger, redpig, Neel and all the other leeches we forgot to mention!
Enjoy some photography while at ring0 @
For our webapp friends, here is an XSS executing at ring 0: javascript:alert(1);
shellcode now executing chmod("/bin/sh", 04755), welcome to ring0
$ sh
# id
uid=1000(julien) gid=1000(julien) euid=0(root)
On x86/x86_64, this issue could be mitigated by three things:
  • the recent mmap_min_addr feature. Note that this feature has known issues until at least See also this LWN article.
  • on IA32 with PaX/GrSecurity, the KERNEXEC feature (x86 only)
  • not implementing affected protocols (a.k.a., reducing your attack surface by disabling what you don't need): PF_APPLETALK, PF_IPX, PF_IRDA, PF_X25, PF_AX25, PF_BLUETOOTH, PF_IUCV, IPPROTO_SCTP/PF_INET6, PF_PPPOX, PF_ISDN, but there may be more. (Update: See RedHat's mitigation)
This patch should be applied to fix this issue.

You can read our advisory here.

Note: this has been featured on Slashdot, OSNews, TheRegister, ZDNet and others


  1. It's not exploitable for code execution on all architectures. My sparc server for instance is safe ;)

  2. It's already been patched, just make sure you've run the update.

  3. I'm safe, I run Windows

  4. One more reason I'm glad to have PaX and GrSecurity.

  5. good thing i run plan9

  6. How about some exploit code??
    First person to release c0de gets a beer on me!

  7. What if you have IPX completely disabled in your kernel? Looking at your discovery, I can see how this would be a problem for people with very modular kernels/

    beer please now

  9. This is one reason so many 64b systems (Tru64 on Alpha being a good example) prevent mapping the first 32 bits of address space. Surprising that Linux doesn't do the same.

  10. > This is one reason so many 64b systems
    > (Tru64 on Alpha being a good example
    > prevent mapping the first 32 bits of
    > address space. Surprising that Linux
    > doesn't do the same.

    ?? First of all - the whole problem has nothing to do with architecture of the used CPU (intel, non-intel, 32bit, 64bit).

    Secondly - Linux also offers such protection, but it was somehow flawed until one of the kernel versions

    3rdly - It is guaranteed on some systems (SVR4) that the fisrt page is always mapped (PROT_READ afair), so linux tries to emulate that behavior via the personality mechanism - - and that is where the bug lied (the one with mapping zero page).

  11. Exploit code has been available at

    Works on all affected kernels: both x86 and x64, 4k stacks or 8k stacks, cred framework or not. Disables SELinux, AppArmor, LSM, and auditing. Also plays an embedded movie if the host is up to it.


  12. Can anybody explain why only works once?

  13. Yet another reason to use some alternative with better track record wrt security, like Solaris or *BSD.

  14. Looks like it's finally kernel upgrade time!
    Goodbye Linux_2.6.19, I'll miss you.


  15. Don't use the one from securityfocus, they have an old version of the exploit.

  16. UNABLE TO MAP ZERO PAGE! on up to date Fedora with SELinux. Problem addressed by Red Hat when fixing CVE-2009-1895 recently?

  17. Why can't the kernel track the process that map page zero and does extra stuff when switching from user mode to kernel mode (update mmu to make it not excecutable, ...)

    Of course this will slowdown these processes but are there performance program that depend of that ?
    Wine ?

  18. Looks like you where to fast when you thanked Dan, because SELinux does indeed stop this:

    $ LANG=C sh
    runcon: invalid context:
    unconfined_u:unconfined_r:initrc_t:s0-s0:c0.c1023: Invalid argument

  19. Doesn't work with SELinux, although you claim the opposite in the source:

    runcon: invalid context:
    unconfined_u:unconfined_r:initrc_t:s0-s0:c0.c1023: Invalid argument

    and the raw audit message for this:
    localhost.localdomain type=AVC msg=audit(1250278420.753:27501): avc: denied { mmap_zero } for pid=16933 comm="exploit" scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=memprotect

    So obviously you were to fast when you thanked Dan for "great SELinux bypass".

  20. Fedora's SELinux policy (asuuming you leave it enforcing) protects from the exploit (runcon can't change the type).

  21. So there's actually two bugs. One is NULL pointer dereference and the other is allowing to mmap (presumably unmmapable) memory at 0x0 location (even if /proc/sys/vm/mmap_min_addr > 0).

  22. Here's a reply to some of the comments (not all, sorry):

    - @Anonymous: you're correct, about SPARC. Interestingly, IA32 could also be safe but is not for performances reasons (unless you use Linux 2.0 or PaX KERNEXEC/UDEREF). x86_64 however killed segmentation :(
    - About mapping to Null. This should be protected by mmap_min_addr since Linux 2.6.23. Last month, Tavis and I published a way to bypass it by using personalities and Pulseaudio. Brad Spengler then implemented this technique in an exploit and noticed that it worked even without the Pulseaudio trick. The reason was the default SELinux policy allowing unconfined users to mmap at address zero.

  23. This definetly does not work on fedora with selinux enforcing.

  24. my fedora 11 with SELinux enforcing is also safe, the exploit doesnt work or did i miss something?

  25. It did exploit Fedora SELinux up until August 13, then was patched. I successfully exploited Kernel with this mechanism.

    Julien can u give more info about this vuln and how to trigger it.

  27. Is it not normal procedure to inform the Kernel maintainers before publishing an exploit to the world? It took until 13th August for a patch to be released.

  28. @John: I have no idea what you're talking about. We also worked on the patch, which was released even before the advisory.

    I even link to it from the blog post.