PaX/Grsecurity --> KSPP --> AOSP kernel: Linux kernel mitigation checklist( WIP)
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
- 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_STRUCTLEAK was originally designed to prevent vulns like CVE-2013-2141, to ensure that any structures contains __user attributes will be fully initialized. This feature is ported to vanilla kernel and merged in v4.11, which is called GCC_PLUGIN_STRUCTLEAK.
- [GRKERNSEC_RANDSTRUCT], is a Grsecurity feature randomize the number of sensitive kernel structures at compile time and ported it to the mainline and merged in v4.12.
- 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( pretty similar to BIGBRO's Land-here proposal), ARMv8.3's pointer authentication( can't support kernel CFI in recent patch), etc. CFI research is one thing while a good engineering of kernel CFI implementation is another. You'd have to fix more issues than expected. Although there are some design/implementation( e.g: kCFI, etc) other than PaX's RAP. But it will be a long way to make them production-ready. PaX's RAP is still the only production-ready kernel CFI solution( update: June 2017).
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 tried to port PAX_REFCOUNT to vanilla kernel, which is called HARDENED_ATOMIC. But vanilla kernel community chose Peter Zijlstra's implementation which utilized kref to achieve the similar goal. Good news is this feature will enabled by default in >=v4.11. Unfortunately, it's not strong as PAX_REFCOUNT covered almost every single corner of the code. Anyway, it will raise the bar for attackers but still...a better-than-none solution.
PAX_USERCOPY kills heap overflow bug when the memory copy occurs between userspace and kernel space in either direction. The 1st version developed by Spender in 2009 and added into PaX later. HARDENED_USERCOPY is part of PAX_USERCOPY being ported to linux kernel in v4.8.
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
- W^X for x86 is merged in v4.4.
- arm64's implementation merged in v4.10.
- This feature caught EFI regions with RMX permission, which is a perfect place for ret2dir exploit. A workaround fix merged in v4.6. For the case of kernel with EFI stub, you should ask Spender about situation hardening solution once the ret2dir paper was out.
Linked list hardening
- It raise the BUG() when corruption is detected. Merged in v4.10.
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.
PaX/Grsecurity added xor operations on slab pointers in 2016 and it's being ported to the vanilla kernel named as SLAB_FREELIST_HARDENED, merged in v4.14.
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. The software-based PAN emulation for arm64 is merged in v4.10 and AOSP maintainers backport it for 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.
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.
single/per-task stack canary entropy
Linux kernel has been using weak entropy on stack canary for years and it has been fixed( copy+paste from PaX/Grsecurity) and merged in v4.12, while PaX/Grsecurity solved it since 2011.
heap/stack gap protection
An old problem has been weaponized and named as "Stack Clash" from excellent security research by Qualys. Linux mainline kernel had a fix which copy+paste some code from PaX/Grsecurity written in 2010. All in all, PaX/Grsecurity mitigate this whole exploit vector since 2010.
FORTIFY_SOURCE for linux kernel
Buffer overflow were popular back in old days and gcc/glibc introduced a mitigation is called "FORTIFY_SOURCE" perform some detections during compile time and runtime( compiler left a wrapper func do the runtime check) due to different circumstances back in 2004. Arjan van de Ven implemented it for linux kernel in 2005 but it never make it to the upstream back then. A few years after, PaX team/Spender did an experimental version of FORTIFY_SOURCE based on Arjan's code in 2009 but they chose not to merge it in PaX/Grsecurity due to some reasons, e.g: a little security profit vs. perf impact. This feature being coincidental implementation and merged in v4.13 lately.
Greg Kroah-Hartman proposed this feature to prevent the modification of data at runtime and it's merged in v4.11. Not sure if he "borrow" the code from what PaX/Grsecurity does in kernel/kmod.c back in 2013.
Write-up about KSPP:
- security things in Linux v4.3
- security things in Linux v4.4
- security things in Linux v4.5
- security things in Linux v4.6
- security things in Linux v4.7
- security things in Linux v4.8
- security things in Linux v4.9
- security things in Linux v4.10
- security things in Linux v4.11
- security things in Linux v4.12
- security things in Linux v4.13