Since the PaX Team is still stalling the creation of their first blog post by doing "real work" like being the first to have a working x86 Linux kernel compiled with clang, or previously being the first to have it working on amd64, I decided to write yet another post. The discussion for today's topic will be somewhat short, as I think the data at the bottom is more interesting and speaks more to my point, which is this: the benefit of using grsec/PaX cannot be measured as simply a sum of its individual features. There's another important factor involved; though intangible in itself, it is exhibited through everything we produce: a security mindset. Being a "bug fetishist" isn't a requirement (and tends to produce a security interest in fame only), but rather a real concern for the security of our users and the security of our software.
Hallmarks of a security mindset include:
Looking for new features that could impact current protections or security boundaries
Looking for new features that could greatly increase attack surface
Spotting new code that's been carelessly written
Developing regression tests for protections
Not assuming, auditing
Anticipating user error/carelessness and preventing it
Staying on top of the latest security research/developments
Hallmarks of the rest (for illustrative purposes, we'll call them "Linux kernel developers") include:
Talking for the sake of hearing one talk, with the knowledge that no progress will be made
Not following up to ensure a vulnerability is fixed
Taking several months to resolve known vulnerabilities (distros can add months to this)
Never doing a single grep for CONFIG_GRKERNSEC_PROC_MEMMAP since ASLR was introduced
Preventing exploitation of vulnerabilities that affect the upstream kernel is often a thankless job. We don't publicize this every time it happens, though I have indulged myself from time to time. The lack of a security mindset is what accounts for upstream ripoffs of grsec features ultimately being incomplete or improperly implemented. Code will go in following an initial interest, but no single person will stick around years later to make sure it's still correct. A prime example of this is constifying of function pointers in the kernel. While in upstream it was confined to a few struct types since 2007, it was expanded a great deal in grsec and maintained until today (I'm even nice enough to make security_ops and selinux_enable read-only under KERNEXEC). Upstream never maintained constification since the initial patchset. Occasionally I'd complain about this publicly, and a spurt of interest would follow, only to be unmaintained yet again. Often times someone would make the effort of submitting all the constifying patches from grsec only to see a fraction of them applied (with no reason for the rest to not be applied). There's no eye for consistency or quality, just the name and a facade of security. There's likewise no room in a security mindset for NIH syndrome -- not only is it foolish to ignore the contributions of others, it's irresponsible for those that have a responsibility to their users.
To more concretely demonstrate the previously unseen benefits of a security mindset, I've provided below a list of unpublicized protections present in grsec/PaX compared with their (sometimes 9 year late) rediscovery in public. It's not a complete list (by any means ), but contains some of the items that were publicized recently and some others from recent memory.
Disabled merging of slub caches:
Added to PaX in April 2009
Copied as part of KERNHEAP Phrack article in June 2009
Suggested by upstream for heap hardening (with no results) in March 2011
Restricted /proc/slabinfo for non-privileged users:
Added to grsec as part of CONFIG_GRKERNSEC_PROC in 2002 after a discussion with noir
Suggested upstream in March 2011
eip/esp properly protected in /proc/pid/stat:
Added to grsec in first version of CONFIG_GRKERNSEC_PROC_MEMMAP, pre-2002
Fixed in April 2009 by Jake Edge from LWN, because nobody else bothered to write a patch even though the technique had been published/presented
start_code/end_code properly protected in /proc/pid/stat:
Added to grsec in first version of CONFIG_GRKERNSEC_PROC_MEMMAP, pre-2002
Not fixed in April 2009, despite the same exact kind of infoleak being fixed in the same file
(the wchan part was misguided based on the wrong interpretation of Tavis/Julien's work that didn't even use wchan)
Finally submitted upstream after Kees Cook (post-prodding) grepped for CONFIG_GRKERNSEC_PROC_MEMMAP in grsec, in March 2011 (CVE-2011-0726)
/proc/pid/auxv properly protected against ASLR infoleaking:
Added to grsec in August 2007
Vuln rediscovered in January 2011
Submitted to LKML in February 2011 (with no fixes yet, CVE-2011-1020)
/proc/pid/syscall properly protected against infoleaking:
Added to grsec in 2008 when feature was introduced in 2.6.28
A good gut feeling (unfortunately with no results)
It shows that "I didn't put too much thought into /proc/pid/syscall"
Submitted to LKML in February 2011 (with no fixes yet, CVE-2011-1020)
/proc/pid/stack properly protected against infoleaking:
Added to grsec in 2008 when feature was introduced in 2.6.28
Submitted to LKML in February 2011 (with no fixes yet, CVE-2011-1020)
Kernel poison values not pointing into userland:
Added to PaX in February 2008
Some of them fixed in July 2008
ACPI Interpreter hardened against physical memory reads/writes:
Added to PaX in October 2007
Fixed (either silently or they weren't actually aware what it was they fixed) in February 2011
Module loader hardening (proper RX/RW separation):
Added to PaX in November 2005 (when PaX added module support to KERNEXEC)
Just added to 2.6.38 in March 2011 as a debug option
Updates (as I remember to add them):
04/26/2012:
get_robust_list() protected against infoleaking
The get_robust_list() ASLR infoleak finally fixed upstream late April 2012 after I explicitly reported the vulnerability to Kees Cook. The fix for the infoleak had been in plain sight (surrounded by ifdefs of a feature to remove ASLR infoleaks) in grsecurity since 2009.
11/04/2015:
wchan protected against kernel infoleaking
Finally fixed upstream in November 2015 via this commit. It's not known when it was fixed in grsec, as my current set of old patches only goes back to Sept 10th 2004, but it was fixed in that patch and in all patches since.
08/20/2017:
move_pages() protected against suid ASLR bypass
Finally fixed upstream in August 2017 via this commit, over 11 years after introduction of the vulnerability in 2006. This vulnerability (and the same incorrect permission check in migrate_pages()) was fixed in grsecurity in 2009.
Enjoy the rest of your weekend,
-Brad