New Linux Kernel Flaw Allows Null Pointer Exploits
Trailrunner7 writes "A new flaw in the latest release of the Linux kernel gives attackers the ability to exploit NULL pointer dereferences and bypass the protections of SELinux, AppArmor and the Linux Security Module. Brad Spengler discovered the vulnerability and found a reliable way to exploit it, giving him complete control of the remote machine. This is somewhat similar to the magic that Mark Dowd performed last year to exploit Adobe Flash. Threatpost.com reports: 'The vulnerability is in the 2.6.30 release of the Linux kernel, and in a message to the Daily Dave mailing list Spengler said that he was able to exploit the flaw, which at first glance seemed unexploitable. He said that he was able to defeat the protection against exploiting NULL pointer dereferences on systems running SELinux and those running typical Linux implementations.'"
Actually, it's already been fixed as of 2.6.31-rc3. Interestingly enough, the code by itself was fine until gcc tries to re-assign the pointer value upon compiling. Steven J. Vaughn-Nichols had a decent write-up about it in Computerworld.
C|N>K
This is arguably more of an issue in the compiler than in the kernel,
Not completely... from the SANS Storm Center, the code was as follows:
struct sock *sk = tun->sk;
if (!tun) // if tun is NULL return error
return POLLERR;
The error was that the compiler optimized away the if statement, assuming that tun had already been initialized. The check should have been placed before the sock variable referenced it. Not entirely obvious maybe, but then again, it should have been checked before the assignment.
Ok, I know I shouldn't be feeding the troll, but read the article: the kernel source itself is perfectly fine, is the compiler that optimizes the check away.
Absolutely not. The code itself has a severe bug: If tun is a null pointer then it invokes undefined behaviour. Undefined behaviour means anything can happen. Anything can happen means a severe bug, especially in kernel code. The optimizing compiler just turned C source code that was buggy, but not obviously enough for the programmer, into assembler code that would have been obviously buggy to anyone. Most definitely not the fault of the compiler.
In this case, it is tun->sk, not &(tun->sk) which is being loaded, however the pointer arithmetic which generates the address happens first. If tun is NULL then this is NULL + {the offset of sk}. While dereferencing NULL is explicitly not permitted, pointer arithmetic on NULL is permitted, and dereferencing any non-NULL memory address is permitted.
Raven, I've seen you make the same comment a few times in this story. Please stop pushing this nonsense.
The language standard calls * and -> operations "dereferencing". The way it works is that tun->sk dereferences the whole struct, then hands you the sk field from it.
When you implement this in your compiler you do an address computation first then load only the field because you don't want to load the whole struct when you don't need to, but that's an implementation detail. The compiler is required to act as if the pointer tun were being dereferenced.
It would be a major missed optimization bug if the compiler didn't eliminate the later if (!tun) operation. This is a case where the input code is simply wrong.