AD3018: EnableArmPAC¶
Summary¶
| Property | Value |
|---|---|
| ID | AD3018 |
| Name | EnableArmPAC |
| Category | Security |
| Severity | Warning |
| Applies to | ELF (Linux/Unix) - AArch64 |
Description¶
This rule checks that AArch64 ELF binaries have ARM Pointer Authentication Codes (PAC) enabled. PAC provides hardware-based protection against Return-Oriented Programming (ROP) attacks by cryptographically signing return addresses.
Why This Matters¶
ARM Pointer Authentication (PAC) provides cryptographic protection for pointers, making ROP attacks cryptographically expensive to execute. Unlike software canaries, PAC uses hardware-accelerated cryptography that cannot be bypassed through information leaks alone.
Cryptographic vs. Randomization Defense¶
Stack Canary (randomization):
- Random value on stack
- If attacker leaks it, defense broken
- One leak = complete bypass
PAC (cryptographic):
- Cryptographic signature per pointer
- Signature depends on: pointer, context, secret key
- Leaking one signature doesn't help with others
- Key is in hardware, cannot be extracted
How PAC Protects Return Addresses¶
; Function prologue
paciasp ; Sign x30 (link register) with SP context
stp x29, x30, [sp, #-16]!
; Function body...
; Function epilogue
ldp x29, x30, [sp], #16
retaa ; Verify signature, then return
; If tampered → exception
PAC Key Architecture¶
| Key | Purpose | Scope |
|---|---|---|
| APIAKey | Instruction addresses | Per-process |
| APDAKey | Data pointers | Per-process |
| APIBKey | Alt instruction auth | Per-process |
| APDBKey | Alt data auth | Per-process |
| APGAKey | Generic auth | Per-process |
Keys are managed by the kernel and inaccessible to userspace.
Security Properties¶
| Property | Benefit |
|---|---|
| Context binding | Signature includes SP, prevents reuse |
| Hardware keys | Cannot be extracted |
| Per-pointer signature | Each pointer independently protected |
| Speculation safety | PAC operations are speculation barriers |
Attack Difficulty with PAC¶
Without PAC:
1. Overflow buffer
2. Overwrite return address with ROP chain
3. Done
With PAC:
1. Overflow buffer
2. Overwrite return address
3. Need valid PAC for new address
4. PAC = f(address, context, secret_key)
5. Can't compute without key
6. Attack fails
PAC + BTI Combined Protection¶
| Attack Type | PAC Alone | BTI Alone | PAC + BTI |
|---|---|---|---|
| ROP | Blocked | Partial | Blocked |
| JOP | Partial | Blocked | Blocked |
| COP | Partial | Blocked | Blocked |
Using both provides comprehensive protection.
Performance Characteristics¶
| Operation | Overhead |
|---|---|
| PACIA/AUTIA | 1-3 cycles |
| Per function call | ~2 extra instructions |
| Overall application | 1-5% |
Hardware acceleration makes PAC practical for production.
Deployment Status¶
| Platform | PAC Support |
|---|---|
| Apple iOS 12+ | Mandatory |
| Apple macOS 11+ | Mandatory |
| Android 12+ | Optional, encouraged |
| Linux 5.0+ | Kernel support |
- ROP protection: PAC signs return addresses to detect tampering
- Cryptographic security: Uses hardware keys for signing
- Low overhead: Minimal performance impact with hardware support
- Defense in depth: Complements BTI for comprehensive control-flow protection
Performance Considerations¶
PAC is designed for production use with minimal overhead:
| Metric | Impact |
|---|---|
| Runtime overhead | 1-5% typical |
| Per-function cost | 2 extra instructions |
| Memory overhead | None (uses pointer bits) |
| Hardware requirement | ARMv8.3-A+ |
Operation costs:
| Instruction | Cycles |
|---|---|
| PACIA/PACDA | 1-3 cycles |
| AUTIA/AUTDA | 1-3 cycles |
| RETAA | Same as RET |
Workload impact:
| Workload Type | Overhead |
|---|---|
| Compute-bound | 0.5-1% |
| Call-heavy | 2-5% |
| I/O-bound | Negligible |
Trade-offs: - All code in the call chain should be PAC-enabled for full protection - Mixing PAC and non-PAC code reduces security benefit - Libraries should be recompiled with PAC support
How PAC Works¶
- On function entry: The return address is signed using
PACIASPinstruction - Signature stored: The PAC is stored in unused upper bits of the pointer
- On function return: The signature is verified using
AUTIASPorRETAA - Tampering detected: If the PAC doesn't match, an authentication failure occurs
function:
paciasp ; Sign return address with key A and SP
stp x29, x30, [sp, #-16]!
...
ldp x29, x30, [sp], #16
retaa ; Return with authentication
How to Fix¶
Compile with branch protection¶
# Enable PAC for return addresses
gcc -mbranch-protection=pac-ret -o myapp myapp.c
# Enable both BTI and PAC (recommended)
gcc -mbranch-protection=standard -o myapp myapp.c
# Clang equivalent
clang -mbranch-protection=pac-ret+bti -o myapp myapp.c
Verify the fix¶
# Check for PAC instructions
objdump -d myapp | grep -E "paciasp|autiasp|retaa"
# Check ELF properties
readelf -n myapp | grep -i "PAC"
Example¶
Fail: Binary does not have PAC enabled
Pass: Binary has PAC enabled
Requirements¶
- Compiler: GCC 9+ or Clang 8+
- CPU: ARMv8.3-A or later (with FEAT_PAuth)
- Kernel: Linux 5.0+ for PAC support
See Also¶
- AD3017: EnableArmBTI - Branch Target Identification
- ARM PAC Documentation