Root exploit for Linux kernel published
Brad Spengler, the developer behind the Grsecurity project, has published an exploit for a vulnerability in the Tun interface in Linux kernel 2.6.30 and 2.6.18, used in Red Hat Enterprise Linux 5 (RHEL5), which can be exploited by attackers to obtain root privileges. Of particular interest is the fact that the exploit is even able to circumvent security extensions such as SELinux. According to Spengler's report, the vulnerability is only found in these two versions of the kernel. The core of the problem is a normally non-exploitable null pointer dereference, which becomes exploitable due to the GCC's optimisation function.
The interplay between the vulnerability and the trick for getting past SELinux is a little fiddly. The Internet Storm Center (ISC) has taken a brief look at the vulnerability and has identified the following code as being responsible for the problem:
static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
struct sock *sk = tun->sk; // initialize sk with tun->sk
return POLLERR; // if tun is NULL return error
According to this,
if (!tun) should return an error is it is 0 (null), but the compiler optimises the 'if' block out of existence, because the variable has already been assigned/dereferenced. As a result, the kernel may try to access the address 0x00000000, which an attacker can direct to their own code. Marcus Meissner from SUSE has confirmed to heise Security, The H's associated publication in Germany, that the problem exists in principle.
Meissner points out, however, that two other conditions must be met for the exploit to work. The code must be able to open the /dev/net/tun device. The exploit uses loadable modules from PulseAudio which are set as SUID in some distributions, to do this. The code must also be able to disable the "mmap_min_addr" exploit protection function, something which Spengler achieves by taking advantage of an error in the implementation of 'personalities'.
The solution to the problem is, by unanimous agreement, very simple – to prevent the test from being optimised to oblivion, the value must be tested before the pointer is assigned. The bug is reported to be fixed in kernel version 18.104.22.168.
Future kernel versions will be compiled using the "fno-delete-null-pointer-checks" option, so that the compiler no longer eliminates checks for null pointers. A debate on lwn.net shows a split in opinion on whether this is GCC optimising code to breaking point, or a programming error.
- Linux 2.6.30+/SELinux/RHEL5 test kernel 0day, exploiting the unexploitable, advisory from Brad Spengler
- A new fascinating Linux kernel vulnerability, advisory from ISC.
- Linux 2.6.30 exploit posted, advisory from lwn.net.