Null pointers, one month later
C programmers normally expect that an attempt to dereference a null (zero) pointer will result in a hardware exception which, in turn, causes the program to crash. This happens not because there is anything special about a pointer containing zero, but because the trick of not mapping valid memory at the bottom of the virtual address space has been known and used for decades. If no valid memory is mapped near address zero, the hardware will trap attempts to access memory in that range; that includes attempts to dereference null pointers. It is a useful setup which minimizes the damage caused by misuse of null pointers.
The only problem is that, in the kernel environment, there is no guarantee that no valid memory is mapped at the bottom of the address space. The default is to not map anything there, but applications can request, via the mmap() system call, that the lowest addresses be made valid. So the null pointer address can be made to point to real memory, and this can happen entirely under the control of user space. User-space addresses remain valid when running in the kernel, so, if the kernel can be made to dereference a null pointer, it will be accessing user-controlled memory. Should the kernel try to jump to a null pointer, it will be running user-controlled code directly. Needless to say, this sequence of events would not be good for the security of the system.
After the July disclosure, it was reasonably evident that more null-pointer vulnerabilities had to exist in the kernel. Such bugs are easy to create; all that is required is a missing initialization. A new function pointer added to a structure will be silently set to null by the compiler in every declaration which does not include an explicit initialization for that pointer. Kernel programmers may be diligent about checking for null pointers, but they are human and will miss an occasional check. At times, these checks have been actively discouraged on the reasoning that dereferencing the pointer would, by virtue of oopsing the kernel, provide the same information as the check. For all of these reasons, one must conclude that there will be other situations in which the kernel can be tricked into dereferencing null pointers.
Given that, it would behoove us all to build our systems in ways which are resistant to null-pointer attacks. The /proc/sys/vm/mmap_min_addr parameter was meant to be the first line of defense here; it specifies the lowest address which can be mapped by unprivileged user-space code. Unfortunately, this protection proved porous. Systems with SELinux running, as it turns out, allowed "unconfined" users to map low memory regardless of the mmap_min_addr setting. For many other systems, it was possible to exploit a problem with pulseaudio to run code with the SVR4 personality, which resulted in a mapped zero page. All told, these problems enabled an attacker to bypass the low-memory limits and exploit null-pointer vulnerabilities.
On August 13, another null pointer vulnerability turned up; this one resulted from the combination of a missing function pointer initialization and a failure to check the pointer before jumping to it. It was an easily exploited hole; demonstration code was duly posted and there have been reports that attack code is already attempting to use this vulnerability. The kernel itself was patched quickly, even if the commit which closed this vulnerability was less than forthcoming about the problem:
Linus did mention the problem in the 2.6.31-rc6 announcement, though:
So, do "we" really have all of those issues fixed? We do not, though some important progress has been made in that direction. Take Fedora as an example: the SELinux policy problem which unconditionally allowed "unconfined" users to map low memory has been fixed; as a result, Fedora systems with SELinux running in the enforcing mode are not vulnerable. But the underlying means by which security modules bypass the mmap_min_addr check has not been fixed. So unpatched Fedora systems with SELinux in permissive mode are vulnerable, even though systems with SELinux disabled entirely are not. Updates for Fedora were released on August 15, two days after the disclosure of the vulnerability. Two days may seem slow for a problem of this nature, but, as it happens, only one distributor - Debian - got an update out more quickly.
Red Hat has not, as of this writing, issued an update for this
vulnerability. That is unfortunate because most RHEL systems are
vulnerable as the result of a policy choice made by Red Hat. RHEL systems, by
default, allow "unconfined" users to map low addresses addresses.
Red Hat's Dan Walsh explains: "We
are not planning on changing the default in RHEL5, to maintain backwards
compatibility.
" So, because compatibility trumps security, RHEL
systems (and those running distributions based on RHEL) remain vulnerable
to a trivial local root problem with exploit code easily available and in use. Not
good.
As of this writing, no other distributors have fixed this problem (though Mandriva's update showed up just before publication). Given that this vulnerability affects every kernel released since 2001, every distribution will have shipped vulnerable kernels. Even those which do not enable SELinux and which have taken steps to mitigate the other zero-page mapping problems should really be moving quickly to close this hole. Leaving the barn door open may not be a wise course of action, even if one trusts the fence which has been built around the barn.
One also should not forget all of those older systems, including embedded systems like DSL routers, which will be exposed to this vulnerability. This hole could be a boon to people trying to liberate the devices they own, but it could also be an easy way to take control of important systems which have long since been forgotten about. 2.4 kernels, too, are affected by this problem; it is easy to imagine that the bulk of these older systems will never be fixed.
One month ago we got an undeniable warning that this kind of vulnerability
was coming. The security of many of our systems has undoubtedly improved
over the course of that month. Even so, the latest null pointer
vulnerability would appear to have taken some distributors by surprise;
important holes have not been closed and updates have, in some cases, been
slow in coming. We can - and should - do better than this.
| Index entries for this article | |
|---|---|
| Security | Linux kernel |
| Security | Vulnerabilities/Privilege escalation |