|
|
Subscribe / Log in / New account

Randomizing the kernel

By Jake Edge
April 10, 2013

Address space layout randomization (ASLR) is a technique that makes it more difficult for security exploits to find the addresses they need to further their nefarious aims. ASLR for user space was added in Linux 2.6.12 in 2005, but the kernel has always used fixed virtual addresses for its code. Back in 2011, Dan Rosenberg proposed changing to a random base address for x86 kernels; more recently, Kees Cook has resurrected and revised that patch set, with an eye toward getting it merged soon.

If user-space code lives at known, fixed locations in the address space, exploits can use that information to reliably do their "job". If the kernel randomizes the location in memory where it loads the executable (along with the mmap() region and stack location), the attack code needs to determine the address some other way. One way would be to brute force the location of the function of interest. That can take time and provide some limited clues to an attentive administrator (lots of processes with segmentation faults, for example), but with enough patience, a local attack will succeed. Remote attacks are harder, but not impossible if the server is helpfully restarted after crashes caused by bad address guesses.

For attacks against the kernel, things are a little different. If the kernel's layout is known, an attack can just use the address it needs, but if the kernel base address has been randomized, things are much trickier. A brute force attempt to find the address of interest is likely to result in a kernel oops, which may also lead to a panic depending on the nature of the error and the value of the "panic_on_oops" sysctl setting. Otherwise, some types of system monitoring might also pick up on repeated oops.

For both the kernel and user space, though, information leaks of "interesting" addresses will allow attacks to be more (or completely) reliable. If the attacker (or exploit) can examine some leaked information to narrow down where the random addresses are, that will make attacks more effective. For user-space programs, most or all of the useful information leaks have been removed over the years. For kernel space, the process has been slower, but with settings like kptr_restrict and dmesg_restrict (both of which default off, but are recommended to be enabled in Cook's patches) many of the leaks have been plugged—but there are still more out there.

For most kernels, though, finding addresses of interest is as easy as figuring out which distribution kernel is being run and then examining it (or its System.map file). That's where the idea of kernel ASLR (KASLR) comes from. If the kernel placed itself at a different, randomly chosen base address on each boot, exploits will have a harder time. KASLR is a bit of a misnomer, though, as the layout of the address space isn't randomized, just the base physical and virtual addresses where the kernel gets loaded.

So, conceptually, Cook's patches are fairly easy to understand. They simply randomize the location of the kernel code each time it boots. The actual patches are a bit more difficult to follow. The first creates a new aslr.S x86 assembly code file that is used early in the boot to calculate a base address for the kernel. It uses the RDRAND instruction available on recent Intel CPUs to get a random number from the hardware or the RDTSC instruction to create a pseudo-random number from the low-order bits in the time stamp counter (TSC). There are also some utility routines in that file. One calculates whether the kernel will fit at the physical address where it is to load, while another looks for "noaslr" on the kernel command line to disable KASLR.

The second patch adds the ability to relocate the kernel for 64-bit systems. Currently, 32-bit x86 kernels can be made relocatable through the use of arch/x86/tools/relocs, but in order to support KASLR, relocs needed to work on 64-bit kernels too. Cook's patch refactors the source and changes the build to create relocs_32 or relocs_64 as appropriate.

The heart of the changes comes with the third and final patch. It creates a RANDOMIZE_BASE build configuration parameter that must be enabled to get KASLR. The changes ensure that a random base address gets chosen at boot time, and that the kernel gets loaded there. The patch also makes the interrupt descriptor table (IDT) read-only for "an added security benefit". That particular piece is somewhat unrelated to the rest, which led Ingo Molnar to request that the read-only IDT piece be split out into a patch of its own.

A recent posting by Brad Spengler and the PaX Team that was critical of KASLR was mentioned in the patch set, but Cook believes that "the benefits of this feature in certain environments exceed the perceived weaknesses". When asked for clarification, Cook noted that there are two main weaknesses cited:

1- it depends on address location secrecy and leaks are common/easy.
2- it has low entropy so attack success rates may be high.

For certain environments, the address exposure issue is lessened, Cook continued. In particular, processes running on virtualized guests, remote processes, and contained processes (e.g. via seccomp filters) will all find information leaks difficult to access. The entropy for the existing patch is eight bits at best (it could be less depending on the e820 memory map). That gives attackers just a small (< 1%) chance to guess the right address.

But, as H. Peter Anvin pointed out, an attacker may not be targeting a single system: "a bot might as well target 256 different systems and see what sticks". Cook and others noted that the other 255 crashed systems should be helpful in alerting someone, whether the targeted systems were all run by the same organization or not. Cook also elaborated on the situation without KASLR:

If an attacker targets multiple distinct systems across a wide range of system owners, instead of landing the exploit against all of them, they'll get less than 1% of them, and crash all the rest, removing them (for a while) from the target pool. Without KASLR, they would have landed 100% of the attacks.

In addition, Molnar noted that attackers are often looking for quiet attacks that either succeed or fail without alerting anyone. "Probabilistically crashing the kernel does not fit that requirement."

Though Anvin is a bit skeptical of KASLR (largely due to the small amount of entropy), most in the thread have been supportive of the idea. Cook mentioned that it has been running at Google and is being ported to Chrome OS, so it has some history behind it. The patches are not terribly intrusive, nor large (less than 1000 lines), though they do touch some potentially sensitive parts of the early boot code. Unless some stronger opposition materializes, it seems like something we could see in the mainline sometime this year.


Index entries for this article
KernelSecurity


to post comments

Randomizing the kernel

Posted Apr 11, 2013 12:54 UTC (Thu) by error27 (subscriber, #8346) [Link]

This seems like a very simple and worthwhile step. Ubuntu has kptr_restrict turned on but it's useless without randomization.

It's true that there are still lots of information leaks left. Smatch has a check for some kinds of trivial leaks. I fixed a couple leaks last week.

But if you just keep on plugging away at it, these do get fixed eventually. The quality of kernel code really is getting better. I think of things like this as part of a five year project instead of as an end in themselves.

Randomizing the kernel

Posted Apr 11, 2013 23:58 UTC (Thu) by Beolach (guest, #77384) [Link] (1 responses)

Just a couple weeks back, LWN posted a link to the PaX Team calling KASLR Cargo Cult Security. I quite liked the metaphor they used to illustrate how small a benefit it gives:
this moving target only moves once and is pretty easy to spot.
That said, even w/ only minuscule benefit, I think it might still be worthwhile, if it has an even more minuscule cost. Does anyone know if KASLR has any impact on performance?

Randomizing the kernel

Posted Apr 12, 2013 13:09 UTC (Fri) by tialaramex (subscriber, #21167) [Link]

The earlier link is already mentioned in the article. Deciding whether defences are worthwhile is largely impossible unless you have in mind a specific threat model.

All ASLR-style defences have entirely practical statistical attacks, so if the threat you're modelling wouldn't be phased by that then it's worthless /for that model/. This is a contrast to something like W^X which isn't statistical, an attack that's stopped by W^X is stopped, maybe it can be re-activated by another route, but it can't just be retried (or used against more hosts) with the expectation that it will eventually work.

I make the distinction _entirely practical_ because there are theoretical statistical attacks against a lot of things which we can discount. We quite reasonably don't consider "just guessing" a 128 bit AES secret key to be a practical attack on a scheme using AES encryption for example.

Randomizing the kernel

Posted Apr 18, 2013 12:56 UTC (Thu) by heijo (guest, #88363) [Link]

Why not compile with one function and one global variable per section, keep section-based relocations in the kernel image, and then randomly shuffle the sections at boot?

That would only have a slight boot time and kernel image size overhead, both of which are irrelevant for servers, and probably not an issue anywhere else.

This way, guessing would be impossible, and any "leaks" would not give any information on the location of other functions or data other than the "leaked" one.


Copyright © 2013, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds