Setjmp and longjmp
In 2003, Crispin Cowan, Steve Beattie, John Johansen and Perry Wagle, from
Immunix, published PointGuard™: Protecting Pointers from Buffer Overflow
Vulnerabilities,
boiling down to the idea of protection code pointer by xor
‘ing them with a
cookie.
In 2003, Microsoft filled the patent US7716495B2,
for storing a list of pc
, to verify that the restored one is valid.
In December 2005, Ulrich Drepper added stack pointer and instruction pointer mangling for i368 and amd64 in the glibc.
In September 2015, Josh Gao from Google added setjmp cookies for AArch64 arm x86 and amd64.
In May 2016, Theo de Raadt implemented,
with the help of Mark Kettenis, for amd64, also implemented a cookie-based
mitigation, xor
‘ing the pc
, fp
and
sp
registers with it, for amd64
. A couple of
days later, Philip Guenther did the same for
i386,
mips64,
powerpc,
hppa!
In October, he also implemented it for arm
As of 2019, this mitigation isn’t available for aarch64, alpha, m88k, sh and
sparc64.
This mitigation, in Theo de Raadt’s words, is based on “an old idea (1999?)”, but I failed to find any sources.
Unfortunately, the same cookie is used to xor
the 3 registers, or for each call to
setjmp
, meaning that to bypass this mitigation, an attacker only has to
either leak the cookie value, or know the value of either sp
, pc
or fp
and its corresponding xor
‘ed value.
Reusing the same cookie also means that an attacker can swap values for pc
,
sp
and fp
with the ones from previous calls to setjmp
.
Finally, only 3 registers are protected, instead of all of them. Granted, the rest
of them doesn’t grant a direct control over the program control’s flow, but
still allows an attacker to mess around.
But, despise those weaknesses, OpenBSD’s implementation was the best available when it landed: covering more registers and with a read-only cookie.
In 2016, Microsoft added defenses around
setjmp
/longjmp
in Windows 10, because they could be used as a CFG bypass. The call to
longjump
validates that esp
is pointing to the current thread’s stack,
checks whether eip
is the current module, as well as an hardcoded list of
possible callsites (setjmp
) offsets.
In 2018, Igor Tsimbalist and Hong J. Lu from Intel added
support
for Shadow Stack in the glibc for i386 and amd64 to stack pointer integrity in
setjmp
/longjmp
.
While OpenBSD’s hardening for setjmp
/longjmp
are decent, Microsoft’s
ones are both simpler and way more effective.
A side note, just for fun:
musl doesn’t
provide setjmp
/longjmp
hardening at all.