CVE-2023-21102 - Breaking Shadow Stack Protection on Android Kernel via Logic Error in `__efi_rt_asm_wrapper`
In 2023, a critical vulnerability named CVE-2023-21102 was found in the Android kernel, specifically in the EFI Runtime wrapper assembly code (efi-rt-wrapper.S). This bug is notable because it lets attackers bypass the kernel’s shadow stack protection—one of the mechanisms meant to harden Linux against control-flow hijacking. This guide will walk you through what happened, break down the vulnerable code, explain its impact, and show you how attackers might exploit it.
Privilege escalation: local, no special rights or user interaction required
- References: AOSP Issue A-260821414 | Upstream patch
What Is Shadow Stack Protection?
Shadow stack is a modern security feature designed to prevent Return-Oriented Programming (ROP) attacks. In essence, it maintains a separate “shadow” copy of return addresses. When a function returns, the CPU checks the shadow stack before executing the return to make sure the address hasn’t been tampered with.
If code in the kernel manipulates the stack or return addresses incorrectly (even unintentionally), an attacker could hijack the control flow and escalate privileges.
The Vulnerability: __efi_rt_asm_wrapper
The heart of this problem is in the assembly wrapper for executing EFI (Extensible Firmware Interface) Runtime Services in the Linux kernel. This code has to run privileged UEFI routines while preserving the kernel’s registers and control settings.
Here’s a simplified excerpt based on the original
/* efi-rt-wrapper.S (simplified) */
__efi_rt_asm_wrapper:
// Save return address
push %rip // Save original return instruction address
...
call *%rax // Call EFI runtime function
...
pop %rip // Restore original return address
ret // Return to caller
This wrapper is supposed to play nicely with the shadow stack mechanism. But a logic bug meant that, in some scenarios, the kernel didn’t maintain shadow stack integrity. That allowed attackers to manipulate the normal stack return address, but not update the shadow stack, thereby bypassing the protection.
The code manipulated the program return address manually but failed to keep the shadow stack in sync
- Manual push/pop of return address means the hardware-enforced shadow stack doesn’t see return address changes.
- RET instruction relies on the shadow stack if enabled, but mismatched stacks can let an attacker trick the system.
This opens a window for privilege escalation if an attacker can control the stack content.
Impact: Local Escalation to Root
Because this bug lives inside a commonly accessible path (EFI runtime wrappers in the kernel), a local attacker (for example, via a malicious app or exploited service running as an unprivileged user) can trigger code that passes through this wrapper. If an exploit controls stack content, it could override return addresses, escaping the intended routine and executing arbitrary code as root in kernel mode.
No extra permissions are needed.
Proof of Concept: Simulated Exploit Flow
To help you picture it, here is a C code snippet to show how an attacker would try to exploit similar logic in kernel space:
// This is a demonstration and should not be used for malicious purposes
void trigger_wrapper_bug() {
// Assume we can map memory to fake a stack
char fake_stack[256];
void *attacker_code = ...; // Points to shellcode
// Overwrite the return address on the stack
*((void **)(fake_stack + RET_ADDR_OFFSET)) = attacker_code;
// Now trigger the EFI runtime service, which uses __efi_rt_asm_wrapper
syscall(SOME_SYSCALL);
// After the wrapper "returns", it will jump to attacker_code!
}
In the real attack, gaining control of the call chain to hit this vulnerable wrapper would be critical. This bug eliminates a crucial defense.
Official Fix
The upstream kernel patch rewrites the wrapper to use the ENDBR and other shadow stack-aware instructions, ensuring the integrity of both the main and shadow stack when calling/returning from EFI routines.
References
- Patch: efi: Fix shadow stack bypass in efi runtime wrapper
- AOSP Bug Tracker: A-260821414
How to Stay Safe
- Patch your devices: Make sure your Android kernel (and Linux systems) are up to date, especially if you use a custom ROM or kernel.
- Follow vendor security bulletins: Watch for security bulletins from Google, your phone OEM, or your Linux distribution.
- Use hardware-secure boot: This bug shows that older security mechanisms can be bypassed if not implemented perfectly. Secure, up-to-date firmware and hardware mitigations help.
Conclusion
CVE-2023-21102 is a sobering example of how even advanced security defenses like shadow stacks can be neutralized by seemingly small logic bugs, especially in complex assembly wrappers. If exploited, it can let any app local escalate to full admin—and is trivial enough that user interaction is not needed.
Always keep your devices current and pay attention to low-level kernel and firmware components—security is only as strong as its weakest link.
Further Reading
- Detailed Patch Explanation (Linux Mailing List)
- Android Security Bulletin - January 2023
Timeline
Published on: 05/15/2023 22:15:00 UTC
Last modified on: 05/24/2023 00:15:00 UTC