Address Space Layout Randomization (ASLR) is a computer security technique that involves randomly positioning the base address of an executable and the position of libraries, heap, and stack, in a process’s address space.
Linux has long had ASLR for user-space programs, researcher Kees Cook has applied to the kernel itself as well.
Linux kernel Bug Attack
Kees Cook says “There is a classic structure to many attacks against the kernel”.
An attacker needs to find a bug either by inspecting kernel code, noticing something in the patch stream, or following CVEs.
The attacker can then use that bug to insert malicious code into the kernel address space by various means and redirect the kernel’s execution to that code.
Expert indicates the easiest ways to get root privileges by executing two simple functions as follows:
The existence of those function has made things “infinitely easier for an attacker”, he said.
Once the malicious code has been run, the exploit will then clean up after itself.
These kinds of attacks rely on knowing where symbols of interest live in the kernel’s address space. Those locations change between kernel versions and distribution builds, but are known (or can be figured out) for a particular kernel. ASLR disrupts that process and adds another layer of difficulty to an attack.
ASLR in userspace randomizes the location of various parts of an executable: stack, mmap region, heap, and the program text itself. Attacks have to rely on information leaks to get around ASLR. By exploiting some other bug (the leak), the attack can find where the code of interest has been loaded.
Randomizing the Kernel’s Location
Cook’s kernel ASLR (KASLR) currently only randomizes where the kernel code (text) is placed at boot time. KASLR “has to start somewhere”, he said.
In the future, randomizing additional regions is possible as well.
One side effect has been moving the interrupt descriptor table (IDT) away from the rest of the kernel to a location in read-only memory.
ASLR is a “statistical defense” because brute force methods can generally be used to overcome it.
“The amount of space available for the kernel text to move around is another problem. The code must be 2M aligned because of page table restrictions, and the space available is 2G. It turns out to be a fair amount less”, says the researcher.
In a completely unconfined system, especially one with local untrusted users, KASLR is not going to be very useful, Cook said. But, on systems that use containers or have heavily contained processes, KASLR can help.
Cook’s patches change the boot process so that it determines the lowest safe address where the kernel could be placed.
The current layout of the kernel’s virtual address space only leaves 512M for the kernel code—and 1.5G for modules.
Since there is no need for that much module space, his patches reduce that to 1G, leaving 1G for the kernel, thus 512 possible slots (as it needs to be 2M aligned). The number of slots may increase when the modules’ location is added to KASLR.
“There are some simple steps developers can take to avoid leaking kernel addresses”, he said.
Using the “%pK” format for printing addresses will show regular users 0, while the root still sees the real address (if kptr_restrict is enabled, otherwise everyone sees the real addresses). The contents of dmesg need to be protected using dmesg_restrict and the kernel should not be using addresses as handles.
Therefore all of those things will make KASLR an effective technique for discomforting exploits—at least in restricted environments.