Starting March 27, 2025, we recommend using android-latest-release instead of aosp-main to build and contribute to AOSP. For more information, see Changes to AOSP.
Stay organized with collections
Save and categorize content based on your preferences.
ShadowCallStack (SCS) is an LLVM instrumentation mode that protects against
return address overwrites (like stack buffer overflows) by saving a function's
return address to a separately allocated ShadowCallStack in
the function prolog of nonleaf functions and loading the return address from
the ShadowCallStack in the function epilog. The return address is also stored
on the regular stack for compatibility with unwinders, but is otherwise unused.
This ensures that attacks that modify the return address on the regular stack
have no effect on program control flow.
On aarch64, the instrumentation makes use of the x18
register to reference the ShadowCallStack, meaning that references
to the ShadowCallStack don't have to be stored in memory.
This makes it possible to implement a runtime that avoids exposing
the address of the ShadowCallStack to attackers that can read
arbitrary memory.
Implementation
Android supports ShadowCallStack for both kernel and userspace.
Enable SCS for the kernel
To enable ShadowCallStack for the kernel, add the following line to the
kernel config file:
CONFIG_SHADOW_CALL_STACK=y
Enable SCS in userspace
To enable ShadowCallStack in userspace components, add the
following lines to a component's blueprint file:
sanitize: {
scs: true
}
SCS assumes that the x18 register is reserved to store the address of the
ShadowCallStack, and isn't used for any other purposes. While all system
libraries are compiled to reserve the x18 register, this is potentially
problematic if SCS is enabled for userspace components that interoperate with
in-process legacy code (for example, libraries that could be loaded by third-party
apps), which may clobber the x18 register. As such, we only recommend
enabling SCS in self-contained components that won't be loaded into legacy
binaries.
Validation
There are no CTS test specifically for SCS. Instead, make sure that CTS tests
pass with and without SCS enabled to verify that SCS isn't impacting the
device.
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2025-06-12 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-06-12 UTC."],[],[],null,["# ShadowCallStack\n\n| **Note:** ShadowCallStack is only implemented for aarch64.\n\nShadowCallStack (SCS) is an [LLVM instrumentation](https://clang.llvm.org/docs/ShadowCallStack.html) mode that protects against\nreturn address overwrites (like stack buffer overflows) by saving a function's\nreturn address to a separately allocated **ShadowCallStack** in\nthe function prolog of nonleaf functions and loading the return address from\nthe ShadowCallStack in the function epilog. The return address is also stored\non the regular stack for compatibility with unwinders, but is otherwise unused.\nThis ensures that attacks that modify the return address on the regular stack\nhave no effect on program control flow.\n\nOn aarch64, the instrumentation makes use of the `x18`\nregister to reference the ShadowCallStack, meaning that references\nto the ShadowCallStack don't have to be stored in memory.\nThis makes it possible to implement a runtime that avoids exposing\nthe address of the ShadowCallStack to attackers that can read\narbitrary memory.\n\nImplementation\n--------------\n\nAndroid supports ShadowCallStack for both kernel and userspace.\n\n### Enable SCS for the kernel\n\nTo enable ShadowCallStack for the kernel, add the following line to the\nkernel config file: \n\n```\nCONFIG_SHADOW_CALL_STACK=y\n```\n\n### Enable SCS in userspace\n\nTo enable ShadowCallStack in userspace components, add the\nfollowing lines to a component's blueprint file: \n\n```\nsanitize: {\n scs: true\n}\n```\n\nSCS assumes that the `x18` register is reserved to store the address of the\nShadowCallStack, and isn't used for any other purposes. While all system\nlibraries are compiled to reserve the `x18` register, this is potentially\nproblematic if SCS is enabled for userspace components that interoperate with\nin-process legacy code (for example, libraries that could be loaded by third-party\napps), which may clobber the `x18` register. As such, we only recommend\nenabling SCS in self-contained components that won't be loaded into legacy\nbinaries.\n\nValidation\n----------\n\nThere are no CTS test specifically for SCS. Instead, make sure that CTS tests\npass with and without SCS enabled to verify that SCS isn't impacting the\ndevice."]]