How Android’s Shadow Call Stack Strengthens Kernel Security

This article explains Android's Shadow Call Stack (SCS) security mechanism, its hardware dependencies, enabling methods, and how it protects return addresses on AArch64 kernels, illustrated with code examples and real‑world deployment results.

OPPO Amber Lab
OPPO Amber Lab
OPPO Amber Lab
How Android’s Shadow Call Stack Strengthens Kernel Security

0x01 Introduction

When discussing kernel stack overflow mitigations, many think of Stack Canary. This article introduces a newer Android security mechanism – Shadow Call Stack (SCS) – that operates silently in recent releases.

0x02 Feature Overview

In a typical function call, the return address is stored on the regular stack, which attackers can overwrite to hijack execution (e.g., via buffer overflow or ROP). SCS, built on LLVM, creates a protected stack frame that stores return addresses separately, preventing such attacks.

0x03 Google Requirements

Since Android R, the AOSP Compatibility Definition Document strongly recommends enabling CFI, SCS, and IntSan. The AOSP kernel from version 5.4 enables SCS by default.

0x04 Dependency Conditions

SCS requires hardware support. It is currently supported on Intel CET for x86_64 and Pointer Authentication for AArch64. In practice, only AArch64 implementations are widely available; LLVM removed x86_64 support in version 9.0 due to performance and security concerns.

0x05 Enabling Method

Developers can enable SCS for the whole kernel or individual user‑space processes by following Google’s guidelines, or by passing -fsanitize=shadow-call-stack to the linker. Functions that must avoid SCS can be marked with __attribute__((no_sanitize("shadow-call-stack"))).

0x06 Security Principle

SCS complements -fstack-protector to provide defense‑in‑depth against non‑linear overflows that tamper with return addresses. On AArch64, SCS uses the X18 register as a pointer to the shadow stack, keeping the address out of regular memory. The following demo illustrates the transformation.

int foo() {
    return bar() + 1;
}

Compiled without SCS (x86‑like assembly):

push   %rax
callq  bar
add    $0x1,%eax
pop    %rcx
retq

Compiled with SCS enabled on AArch64 (relevant instructions highlighted):

str     x30, [x18], #8
stp     x29, x30, [sp, #-16]!
mov     x29, sp
bl      bar
add     w0, w0, #1
ldp     x29, x30, [sp], #16
ldr     x30, [x18, #-8]!
ret

0x07 Functional Risks

SCS relies on the X18 register being free for this purpose. While system libraries reserve X18, third‑party or legacy libraries may use it, which could cause incompatibilities. OPPO collaborated with Qualcomm and MediaTek in 2020 to enable SCS early, demonstrating effective mitigation of return‑address hijacking without compatibility issues.

0x08 Outcome

In the OPPO FIND X3 project, reverse‑engineering of the boot image with IDA confirmed the presence of SCS signatures, validating its deployment.

Although SCS significantly raises device security, it does not protect against all attacks; developers should also employ input validation, memory‑safe programming, and proper permission management.

LLVMAndroid Securityaarch64Shadow Call StackKernel Hardening
OPPO Amber Lab
Written by

OPPO Amber Lab

Centered on user data security and privacy, we conduct research and open our tech capabilities to developers, building an information‑security fortress for partners and users and safeguarding OPPO device security.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.