Contributed by pitrh on from the all tomorrows random gaps dept.
5 weeks ago at d2k17 I started work on randomized kernels. I've been having conversations with other developers for nearly 5 years on the topic... but never got off to a good start, probably because I was trying to pawn the work off on others.
Having done this, I really had no idea we'd end up where we are today.
Here are the behaviours:
- The base set has grown, it now includes a link-kit
- At install time, a unique kernel is built from this link-kit
- At upgrade time, a unique kernel is built
- At boot time, a unique kernel is built and installed for the next boot
- If someone compiles their own kernel and uses 'make install', the link-kit is also updated, so that the next boot can do the work
- If a developer cp's a kernel to /, the mechanism dis-engages until a 'make install" or upgrade is performed in the future. That may help debugging.
A unique kernel is linked such that the startup assembly code is kept in the same place, followed by randomly-sized gapping, followed by all the other .o files randomly re-organized. As a result the distances between functions and variables are entirely new. An info leak of a pointer will not disclose other pointers or objects. This may also help reduce gadgets on variable-sized architectures, because polymorphism in the instruction stream is damaged by nested offsets changing.
At runtime, the kernel can unmap it's startup code. On architectures where an unmap isn't possible due to large-PTE use, the code can be trashed instead.
I did most of the kernel work on amd64 first, then i386. I explained what needed to be done to visa and patrick, who handled the arm and mips platforms. Then I completed all the rest of the architectures. Some architecture are missing the unmap/trashing of startup code, that's a step we need to get back to.
The next part was tricky and I received assistance from tb and rpe. We had to script the behaviours at build time, snapshot time, relink time, boot time, and later on install/upgrade time also.
While they helped, I also worked to create the "gap.o" file without use of a C compiler so that relinks can occur without the "comp" set installed. This uses the linkscript feature of ld. I don't think anyone has done this before. It is little bit fragile, and the various linkers may need to receive some fixes due to what I've encountered.
To ensure this security feature works great in the 6.2 release, please test snapshots. By working well, I mean it should work invisibly, without any glitch such as a broken kernel or anything. If there are ugly glitches we would like to know before the release.
You heard the man, now is the time to test and get a preview of the new awsomeness that will be in OpenBSD 6.2.
(Comments are closed)