PaX/Grsecurity –> KSPP –> AOSP kernel: Linux kernel mitigation checklist( Dec 13 2016)
We should treat security as a whole, just like the combination of PaX/Grsecurity features/code hardening build up a defense-in-depth solution for Linux kernel, which is a core infrastructre we are highly rely on. PaX/Grsecurity is a set of security hardening specific patch that brings the linux kernel security into another level. It’s a great value to make all FLOSS community getting benefit from it. KSPP( Kernel self protection project) was started in Nov 2015 after a disclosure about linux kernel security. This is the 1st time the public had chance to know that linux kernel security might endanger the mobile platform( Android) and IoT devices. KSSP has been trying to port features/code hardening from PaX/Grsecurity to Linux upstream. Bad guys wouldn’t like to see it happen, but it will, a part of it at least;-) KSPP is quite important to Android dev/user community, because AOSP kernel security is highly rely on how KSPP goes. Tor community started a secure Android ROM project is called Mission Improbable based on CopperheadOS lately, which is a good starting point. KSPP matters to our security and privacy is inevitable. I’d like to see more features of PaX/Grsecurity lands in vanilla linux and AOSP kernel and more importantly, give PaX/Grsecurity the credits they deserved.
Thanks to PaX team/Spender, they guys initiated the ALPHA philosophical ideas and implementations of defensive mitigation of system security. PaX/Grsecurity may not be the OMEGA in this field, but I’m damn sure they are the fuc* ALPHA. Also thanks to Kees Cook( not like rockstars from PROJECTZERO, he’s a hidden hero), Daniel Micay( awesome contributor of AOSP kernel and interesting work of libc hardening; And, CopperheadOS may be the only ROM[DO NOT INCLUDE PRIVATE CONSULTING SOLUTION] trying that hard to protect individual’s privacy and digital asset.) and other contributors for FLOSS security.
Before you dive into the devils, plz go get a cup of cofee or green tea and think what the hell is/isn’t security……….
Security is NOT:
- Security is NOT installing a firewall ..
- Security is NOT a Product or Service .. ( by Schneier, Bruce )
- Security is Not a Product; It’s a Process .. ( by Schneier, Bruce )
- A Security Audit is NOT “running a port scan and turning things off” ..
- Security is “Can you still continue to work productively/safely, without compounding the security breach”
- Security is only as good as your “weakest link”
- Security is “risk management” of your corporate resources(computers/people), required expertise, time management, implementation costs, data backup/recovery proceedures …
- Security is a Process, Methodology, Costs, Policies and People
- Security is “Can somebody physically walk out with your computers, disks, tapes, .. “
- Security is 24x7x365 … constantly ongoing .. never ending
Security is “learn all you can as fast as you can, without negatively affecting the network, productivity and budget”
- GCC plugins infrastructure, CYC_COMPLEXITY, SANCOV, merged in v4.8
- HARDENED_USERCOPY is trying to mitigate heap overflow, which is very popular class of bugs in kernel. It was originally based on PAX_USERCOPY, merged in v4.8
- PAX_LATENT_ENTROPY is trying extract more entropy on those functions marked by __latent_entropy gcc attribute at boot time, which is very helpful to embedded system. Now it’s called “latent_entropy” plugin merged in v4.9.
- PAX_REFCOUNT, those reference counter overflow bug can be exploited in scenario where UAF( Use-After-Free) comes into game. PAX_REFCOUNT killed this kind of bug class. Elena Reshetova is trying to port PAX_REFCOUNT to vanilla kernel, which is called HARDENED_ATOMIC.
- PAX_RAP, the strongest CFI implementation so far. The 1st public RAP version was merged in PaX/Grsecurity 4.5.x’s test patch. It’s x86_64 only for now. But it can be ported to other architectures. RAP might utilize the advantage of hardware based implementation, such as Intel’s CET, ARMv8.3’s pointer authentication, etc.
Post-init read-only memory, merged in v4.6
- arm64 vdso Mark vDSO code as read-only, it’s also merged in AOSP kernel for 3.10/3.18/4.1/4.4.
- arm/x86: vdso: Mark vDSO code as read-only, Enable CONFIG_DEBUG_RODATA by default
- arm64: always enable DEBUG_RODATA merged in v4.9
use-after-free is a very popular bug class in kernel and it can be exploited by the adversary to gain information or priviledges.
PAX_MEMORY_SANITIZE does poisoning/sanitization the memory on free to reduces the attack surface. Laura Abbott submitted a similar implementation( as debug options) inspired( which isn’t?;-)) by PAX_MEMORY_SANITIZE and merged in v4.6.
I’m not sure how many incidents were getting involved with easy-to-write null-deref exploit. The truth is there were a lot. It ended by restrict minimal address of memory mapping, which is a trivial mitigation after Spender’s Enlightment framework showed up in those endless crazy party;-) It was a crazy era fulfilled with ignorance and a shame to the defensive side, even not to mention the backdoor fix( “thanks” to the greatest GNU/Linux vendor..well, they wouldn’t call themselves “GNU and slash and Linux” vendor, I suppose;-)) for the mitigation which supposed to protect your digital asset. KERNEXEC/UDEREF are the only options back in those 0ld horrible “one null-deref bug can root them all” days and remeber this: It’s not very long ago.
KERNEXEC, Set [syscall table, IDT, GDT, some page tables] to RO & set [data pages] to NX( Note: some tricks prevent new attacks like ret2dir, ask PaX team/Spender) in x86, which is the strongest implementation of KERNEXEC. Recommended priority selection for different architectures: x86 -> armv7 -> x86_64. Marking kernel pages as RO is very helpful to minimizing the attack surfaces and it’s also an effective way to mitigate physmap spraying. armv7 has done a very similar feature merged in v3.18 and arm64 got one merged in v3.19. On AOSP side, Android-3.10 got a backport( from Qualcom’s BSP out-of-tree patches?).
UDEREF, x86 is the strongest one, as Grsecurity’s blog described. ARMv7 is also a strong implementation. The story of x64/UDEREF is complicated a bit and it has 3 different implementations. The strong one was introduce in Aug 2013. It’s Aug 2016 now…you know what you can do if you’re going to deploy a new production server/desktop.
SMEP( Supervisor Mode Execution Protection), it’s provided by Intel x86( Ivybridge or newer) to achieve a subset functions of KERNEXEC. SMEP will prevent( mmap & exec [SHELLCODE of prepare_kernel_cred/commit_creds] shit, ring the bell?) if kernel attemp to code execution in a page not owned by kernel itself. Unlike KERNEXEC, it’s not able to prevent exploitation of RWX or important data structure.
SMAP( Supervisor mode access prevention), merged in v3.7. It’s provided by Intel x86( Broadwell or newer) to achieve the same goal of UDEREF. But it’s weaker than the current implementation of UDEREF.
PXN( Privileged execute-never), PXN is provided by ARM hardware and it’s a similar feature like SMEP. Weaker than KERNEXEC( Did someone still ask?), that’s for sure. arm64’s PXN implementaion is merged in v3.7, and armv7’s PXN implementation is merged in v3.19. citypw backported it to AOSP kernel and now PXN for armv7 are enabled in AOSP by default in 3.4/3.10/3.14/3.18/4.1/4.4. Unfortunately, 3.4 is EOL already. If you still need to protect old Android devices, try Hardened PoC: PaX for Android. According to Grsecurity’s blog, the 1st PXN implementation of armv7 was from PaX/Grsecurity back in early 2013.
PAN( Privileged Access Never), PAN is a new feature of ARMv8.1 to achieve the same goal like SMAP and it’s merged in v4.3. The shitty thing is that we don’t have ARMv8.1 yet( probably only Cavium’s chip for server), while ARMv8( arm64) is shipping hundred thousands chips for GNU/Linux and Android every day. Customers might not notice their device doesn’t have supposed-to-be-off-the-shell mitigation;-) Fortunately, there’s software-based PAN implementation for armv7 and it’s merged in v4.3. It’s backported to 4.1 by Kees Cook and 3.18 by Sami Tolvanen. Speaking of arm64’s implementation, there’s a patch not merged yet. arm64’s PAN emulation will be taken care of by Google’s maintainers( Backport: 3.18, 4.1, 4.4). Ironically, Linux kernel upstream may be willing to merge software-based PAN implementations for both armv7 and arm64 but PaX’s UDEREF( armv7-only). If we are talking about software-based implementation without taking performance issue into account, we should’ve put security into the 1st priority…You know what I’m talking about, aren’t u;-)
You don’t need to worry about ret2dir if you’re running PaX/Grsecurity w/wo KERNEXEC on the most x86 systems. The orginal authors proposed a defensive solution is called XPFO( eXclusive Page Frame Ownership) and Juerg Haefliger is trying to make it lands into upstream. W & X memory is the cruial condition to physmap spraying. ret2dir is no longer a big threat to the modern kernel since x86( v4.6) and arm64( v4.9) makes all kernel memory X^W. About AOSP kernel, plz see ##KERNEXEC
BPF JIT hardening
This type of attack is aginst variable-length instruction architecture specifically. This problem is almost a disaster in some important application( e.g: Adobe FLash) on Desktop/Mobile. Cu’z it’s more likely a RCE to be appeared. For GNU/Linux server, it’s still an attack vector that we should taking very serious.
Set register type according to is_valid_access() is trying to prevent infoleak from an unprivileged eBPF program read a pointer value from its context, merged in v4.9.
vmalloc kernel stack
Jon Oberheide shared about kernel stack attack surfaces and kernel stack hijacking is still useful to exploit Linux and Android kernel. PaX/Grsecurity moved thread_info off the kernel stack for x86 back in 2011. The GRKERNSEC_KSTACKOVERFLOW( there are some other features including moved thread_info off the stack) was forged in 2014 and the 1st support kernel version is v3.14. Andy Lutomirski( other contributors?) is trying to implement the exact what GRKERNSEC_KSTACKOVERFLOW does and this feature merged in v4.9(x64-only) via:
- fork: Add generic vmalloced stack support
- dma-api: Teach the “DMA-from-stack” check about vmapped stacks
- x86/mm/64: Enable vmapped stacks (CONFIG_HAVE_ARCH_VMAP_STACK=y)
- x86/mm: Improve stack-overflow #PF handling
- virtio_console: Stop doing DMA on the stack
- sched/core: Allow putting thread_info into task_struct
- x86: Move thread_info into task_struct
- iommu/amd: Don’t put completion-wait semaphore on stack
- sched/core: Add try_get_task_stack() and put_task_stack()
- x86/dumpstack: Pin the target stack when dumping it
- x86/process: Pin the target stack in get_wchan()
- lib/syscall: Pin the task stack in collect_syscall()
- sched/core: Free the stack early if CONFIG_THREAD_INFO_IN_TASK
- fork: Optimize task creation by caching two thread stacks per CPU if CONFIG_VMAP_STACK=y
PERF is a fuc*ing serious attack surface. We can’t bear it running by default in production system. Ben Hutchings proposed a patch from PaX/Grsecurity to linux kernel but it rejected by kernel maintainer. Fortunately, Jeff Vander Stoep merged it into AOSP kernel.
Write-up about KSPP: