Missing security features
This is a small arbitrary list of cools and/or interesting mitigations that OpenBSD doesn’t have.
Unfortunately, starting with LLVM 9.0, released the [19 September 2019]](https://releases.llvm.org/), LLVM is now released under Apache License v2.0 with LLVM Exceptions, a license that the OpenBSD people consider incompatible with their philosophy (while it looks like it actually is compatible), so it seems that they’ll be stuck on this particular version, like they used to be with GCC for almost 10 years.
Constification of function points in kernel-land
PAX_CONSTIFY_PLUGIN is a gcc plugin by Emese (ephox)
Revfy and pipacs,
marking all structures containing only function pointers as
read-only. It has been part of grsecurity since August 2011.
This prevents trivial control-flow highjacking by function pointer-overwriting.
Integer overflows in critical functions’ parameters
size_overflow is an other plugin by ephox, written in 2011.
In ephox’s own
This plugin recomputes expressions of function arguments marked by a
size_overflowattribute with double integer precision (
TImodefor 32/64 bit integer types). The recomputed argument is checked against
TYPE_MAXand an event is logged on overflow and the triggering process is killed.
It was added to grsecurity in March 2013, and was thoroughly documented for the occasion.
Automatic initialization of variables
In August 2011, pipacs published his
PAX_MEMORY_STRUCTLEAK gcc plugin,
which zero initialize some local variables that are going to be copied to userland.
In June 2014, Florian Weimer from Red Hat posted a patch on gcc’s mailing list to initialize all local variables to zero.
JF Bastien, compiler engineer at Apple, suggested in November 2018 a patch for clang, to add a flag to automatically initialize variables, either with 0, or with a specific pattern, with only a couple of percent performance impact.
Also in November 2018, Microsoft
flag to its compiler, providing a similar feature, with only noise-level
performance impact. Joseph Bialek, security engineer in the Microsoft Security
Response Center’s Vulnerability & Mitigations team
Between 2017 and mid 2018, this feature would have killed 49 MSRC cases that involved uninitialized struct data leaking across a trust boundary. It would have also mitigated a number of bugs involving uninitialized struct data being used directly. cc @j00ru @TinySecEx
Control Flow Integrity for forward edges
Control-flow integrity usually has two components, one to enforce forward-edges, and the other for backward-edges. In OpenBSD, backward edges are kinda covered by RETGUARD, by forward ones aren’t.
- PaX has RAP, privately since at least 2012, publically since 2015.
- Android uses clang’s CFI for some userland applications since 2017, cross-DSO since 2018, and in kernel-land since 2019.
- HardenedBSD has non-cross-DSO clang CFI since 2017.
- Windows has CFG in Windows 8.1 and Windows 10 since 2015, and even if they removed it from the scope of its bugbounty in 2018, it’s coming back as XFG, taking inspiration for PaX’s RAP.
While most of them have been bypassed in several ways, they’re getting better and better over time, and might force attackers to use data-only attacks instead of ROP and its friends, even in the case of arbitrary reads, arbitrary writes, at arbitrary times.
Kernel stack protections
In 2011, Jon Oberheide and Dan Rosenberg presented STACKJACKING - your way to
at Infiltrate, along with a
prompting pipacs and spender to move
thread_info out of the kernel stack,
port RANDKSTACK to amd64, improve
RANDKSTACK could make things worse, as highlighted in the followup
presentation at SummerCon 11, Stackjacking and Other Kernel
as well as in the accompanying blogpost.
In response, based on Jon Oberheide and Dan Rosenberg’s recommendations, pipacs
PAX_MEMORY_STACKLEAK, to erase completely the kernel stack after
In August 2017, Theo de Raadt
a small random offset to each process’ kernel stack. This can be bypassed
kstack self-discovery technique, as explained in the
slides, if you have a kernel stack memory disclosure, which aren’t
uncommon. By the way, this isn’t the only trick from this slide deck that can
be applied to OpenBSD ;)
segvguard was created by Rafal (Nergal) Wojtczuk around 2001, and discussed in his The advanced return-into-lib(c) exploits: PaX case study Phrack article. It’s a daemon notified by the kernel every time a process crashes with a SIGSEGV, able to temporarily disable the execution of the crashing programs, thwarting bruteforce-based ASLR bypass.
In 2002, spender implemented
When a child of a forking daemon is killed by PaX or crashes due to an illegal instruction or other suspicious signal, the parent process will be delayed 30 seconds upon every subsequent fork until the administrator is able to assess the situation and restart the daemon.
In 2011, it was enhanced to be more severe for suid/sgid binaries:
In the suid/sgid case, the attempt is logged, the user has all their existing instances of the suid/sgid binary terminated and will be unable to execute any suid/sgid binaries for 15 minutes.
Also in 2011,
GRKERNSEC_KERN_LOCKOUT was implemented: if an
KERNEXEC violation is triggered, or an OOPS due to bad
memory access, if the user is root the system will panic, otherwise
the attempt are logged, all the processes from the users are killed,
and the user won’t be allowed to create new process until the system is
This is a bit similar to the idea of trustlevels in OpenBSD, except that it’s: way more granular, proactive and completely automatic. It can also be compared to password bruteforce prevention: increasing delays between tentative, followed by a lockout.
It’s also the only way to make sure that ASLR can’t be bruteforced, even partially. It also acts as a deterrent for unreliable exploits: if the exploit doesn’t work reliably in a single shot, there is no way to launch it again, escalade privileges, and clean the traces.
This grsecurity’s option provide a way to create a group whose members won’t be able to execute any files that are not in root-owned directories writeable only by root. Of course, with interpreters, it’s still possible for a user to execute arbitrary code, but porting a privilege escalation exploit into Python isn’t fun™.
This mitigation can be emulated by chrooting users, and bind mounting everything
noexec, and while it’s not something as
fundamental as ASLR or NX, I still wanted to mention it.