Kernel ASLR on amd64

Recently, I completed a Kernel ASLR implementation for NetBSD-amd64, making
NetBSD the first BSD system to support such a feature. Simply said, KASLR is a
feature that randomizes the location of the kernel in memory, making it harder
to exploit several classes of vulnerabilities, both locally (privilege
escalations) and remotely (remote code executions).

Current design

The current design is based on a specialized kernel called the “prekern”, which
operates between the bootloader and the kernel itself. The kernel is compiled
as a raw library with the GENERIC_KASLR configuration file, while the prekern
is compiled as a static binary. When the machine boots, the bootloader jumps
into the prekern. The prekern relocates the kernel at a random virtual address
(VA), and jumps into it. Finally, the kernel performs some cleanup, and executes
normally.

Currently, the kernel is randomized as a single block. That is to say, a random
VA is chosen, and the kernel text->rodata->data sections are mapped
contiguously starting from there. It has several drawbacks, but it’s a first
shot.

To complete this implementation, work had to be done at three levels: the
bootloader, the prekern and the kernel. I committed several of the kernel and
bootloader patches discreetly a few months ago, to pave some way for real
changes. In the past few weeks, I changed the low-level x86 layer of the kernel
and replaced several hard-coded (and sometimes magic) values by variables, in
such a way that the kernel can run with a non-static memory layout. Finally, the
last step was committing the prekern itself to the source tree.

Future work

  • Randomize the kernel sections independently, and intertwine them.
  • Modify several kernel entry points not to leak kernel addresses to userland.
  • Randomize the kernel heap too (which is still static for now).
  • Fix a few other things that need some more work.

How to use

All of the patches are now in NetBSD-current. Instructions on how to
install and use this implementation can be found
here;
they are inlined below, and probably won’t change in the future.

Make sure you have a v5.11 bootloader installed. If you don’t, build and install
a new bootloader:

    $ cd /usr/src/sys/arch/i386/stand/boot
    $ make
    # cp biosboot/boot /

Build and install a KASLR kernel:

    $ cd /usr/src
    $ ./build.sh -u kernel=GENERIC_KASLR
    # cp /usr/obj/sys/arch/amd64/compile/GENERIC_KASLR/netbsd /netbsd_kaslr

Finally, build and install a prekern:

    $ cd /usr/src/sys/arch/amd64/stand/prekern
    $ make
    # cp prekern /prekern

Reboot your machine. In the boot prompt, enter:

    > pkboot netbsd_kaslr

The system will boot with no further user interaction. Should you encounter
any regression or unexpected behavior, please report it immediately
to tech-kern.

Note that you can still boot a static kernel, by typing as usual:

    > boot netbsd

Availability

This KASLR implementation will be available starting from NetBSD 9. Once it is
stabilized, it may be backported to NetBSD 8. Until then, feel free to test it!

Go to Source
Author: Maxime Villard

Powered by WPeMatico