Taint
Analysis
System Call
Snapshot
Data
Spillage Analysis
ROP
Chain
Generation
IGNI
Kernel Image
CFHP
PE Exploits
Figure 2: IGNI Design Overview
systems, as shown in Table 3, RANDKSTACK can be fully bypassed.
In other words, RetSpill can bypass RANDKSTACK on most of the
Linux distros. The reason is that with panic_on_oops disabled, an
oops in task contexts will not crash the kernel. By using threads to
trigger the payload, if an attempt fails, only the offending thread
will be terminated. The exploit process will be kept intact and can
continue attempts until the exploit succeeds. Such a create-thread-
and-retry attack works only if failed attempts only generate oops
and do not crash the kernel. We demonstrate that this is realistic—
by calling a system call that is known to place “safe" data, such
as NULL pointers, on the kernel stack multiple times to ensure
that failed attempts can only trigger invalid-memory access and
generate oops. To the best of our knowledge, we are the first to
demonstrate that RANDKSTACK can be fully bypassed through
recovery from oops.
STACKLEAK/STRUCTLEAK/INITSTACK.
These protections
prevent attackers from accessing uninitialized memory. More specif-
ically, STACKLEAK [50] clears the kernel stack after each system
call and INITSTACK [51]/STRUCTLEAK [43] ensure stack variables
are initialized before use. In other words, they only prevent user
data spillage from Uninitialized Memory. RetSpill is still effective
by using other user data spillage methods to obtain stack control.
FG-KASLR.
Function Granular Kernel Address Space Layout
Randomization (FG-KASLR) [34] shuffles all kernel function ad-
dresses during boot time to protect the kernel from CFH attacks.
However, function-level randomization is not enough to mitigate
RetSpill. Other code snippets, such as assembly stubs, can also be
compiled into executable sections with fixed offsets in the kernel.
With RetSpill, attackers can look for ROP gadgets in the position-
invariant code and use the arbitrary-read primitive to dynamically
resolve function addresses, as demonstrated by Dang Khac Minh
Le [38]. Then they can trigger the payload again and use the re-
solved function addresses to achieve the exploitation using RetSpill.
KCFI/IBT.
KCFI [60] and Indirect Branch Tracking (IBT) [76]
are two control-flow integrity (CFI) protection schemes merged
into the Linux kernel recently. They both aim to protect the Linux
kernel from forward-edge control-flow hijacking attacks. While
they make it harder, they do not eliminate CFHP attacks.
Due to compatibility issues, even with the presence of these
strong protections, some call targets in the Linux kernel are still
not protected, susceptible to CFHP attacks. For example, in a ker-
nel compiled with KCFI, __efi_call function does not verify its
call targets. An attacker can overwrite the call target and obtain
PC-control. We confirmed with the Linux kernel team that some
call targets are not verified due to incompatibility between some
subsystems and the CFI schemes.
Even with perfect implementation, attackers can still obtain PC-
control by hijacking backward-edge control flow because KCFI/IBT
does not protect them. For example, attackers have demonstrated
the capability of turning a heap-based vulnerability to the kernel
stack (dubbed kernel stack overflow primitive) [30], which can
tamper the backward-edge control flow to obtain PC-control.
Once PC-control is obtained, attackers can carry out RetSpill
despite the presence of KCFI and IBT because RetSpill itself does
not rely on forward-edge control-flow hijacking.
Shadow Stack.
Shadows Stack is proposed to protect backward-
edge control in the Linux kernel. However, it is not implemented yet
in the Linux kernel for the x86_64 architecture. We only analyze its
security guarantee against RetSpill in theory. In kernels protected
by Shadow Stack, attackers can obtain PC-Control from forward-
edge control flow hijacking, but they cannot ROP. To carry out
RetSpill, attackers can use other code reuse attacks that do not rely
on backward-edge control flow hijacking, such as JOP[3]/PCOP[55]
to utilize data spillage from user space,
CFI+Shadow Stack.
In theory, on a kernel deployed with per-
fectly implemented CFI schemes and Shadow Stack, attackers can-
not obtain CFHP anymore, which prevents RetSpill.
6
SEMI-AUTOMATIC RETSPILL
RetSpill has a critical impact on the Linux kernel because it can
not only escalate privilege but also has the potential to achieve
the escalation in a semi-automated pipeline. To show the feasi-
bility of semi-automation, we represent IGNI, a framework that
can semi-automatically generate RetSpill attacks for many real-
world CFH cases. As the goal of this work is to show the feasibility
rather than creating a tool to facilitate malicious attacks, we only
take one attack payload for privilege escalation, namely execut-
ing commit_creds(init_cred) and returning back to user space
gracefully. Creating attacking tools that can comprehensively lever-
age different attack vectors is out of the scope of this paper.
The design of IGNI is shown in Figure 2. IGNI takes a proof-of-
concept (PoC) binary that demonstrates CFHP and a target kernel
image as input, and outputs all the information needed for carrying
out RetSpill. More specifically, it outputs 1) the address of a stack-
shifting gadget that can transfer the initial CHFP into kernel stack
and 2) an ignite function that performs data spillage, invokes the
triggering system call, and leads to PE automatically. By setting the
initial CFHP to the stack-shifting gadget and changing the original
triggering system call to ignite function, the initial crashing PoC
is turned into a full-fledged PE exploit.
Our approach relies on virtual machine (VM) snapshots. We take
a VM snapshot when the triggering system call just enters kernel
space, which ensures deterministic CFHP. Then, we analyze all user