This short article describes how I improved the SLUB allocator in the Linux kernel.
In this talk I showed that the general method of exploiting a double-free error is based on turning it into a use-after-free bug. That is usually achieved by allocating a memory region of the same size between double
free() calls (see the diagram below). That technique is called
However, in case of
CVE-2017-2636, which I exploited, there are 13 buffers freed straightaway. Moreover, the double freeing happens at the beginning. So the usual heap spraying described above doesn't work for that vulnerability. Nevertheless, I've managed to turn that state of the system into a use-after-free error. I abused the naive behaviour of
SLUB, which is currently the main Linux kernel allocator.
It turned out that
SLUB allows consecutive double freeing of the same memory region. In contrast, GNU C library allocator has a
fasttop check against it, which introduces a relatively small performance penalty. The idea is simple: report an error on freeing a memory region if its address is similar to the last one on the allocator's freelist.
A similar check in
SLUB would block some double-free exploits in Linux kernel (including my PoC exploit for
CVE-2017-2636). So I modified
set_freepointer() function in
mm/slub.c and sent the patch to the Linux Kernel Mailing List (LKML). It provoked a lively discussion there.
SLUB maintainers didn't like that this check:
- introduces some performance penalty for the default
- duplicates some part of already existing
- causes a kernel oops in case of a double-free error.
I replied with these arguments:
slub_debugis not enabled in Linux distributions by default (due to the noticeable performance impact);
- when the allocator detects a double-free, some severe kernel error has already occurred on behalf of some process. So it might not be worth trusting that process (which might be an exploit).
Finally Kees Cook helped to negotiate adding this check behind
CONFIG_SLAB_FREELIST_HARDENED kernel option. So currently the second version of the patch is accepted and applied to the
linux-next branch. It should get to the Linux kernel mainline in the nearest future.
I hope that in future some popular Linux distribution will provide the kernel with the security hardening options (including
CONFIG_SLAB_FREELIST_HARDENED) enabled by default.