AD5007: EnableArmPACMachO¶
Summary¶
| Property | Value |
|---|---|
| ID | AD5007 |
| Name | EnableArmPACMachO |
| Category | Security |
| Severity | Warning |
| Applies to | Mach-O ARM64 (Apple Silicon) |
Description¶
ARM Pointer Authentication Code (PAC) provides hardware-based protection against Return-Oriented Programming (ROP) attacks on Apple Silicon (ARM64). PAC signs return addresses and function pointers with a cryptographic signature that is verified before use.
How It Works¶
The rule checks for:
- PAC-related symbols (
__ptrauth,ptrauth_sign, etc.) - Compilation for
arm64earchitecture in DWARF debug info
When PAC is enabled, the CPU: - Signs pointers when they are stored (e.g., return addresses) - Verifies signatures when pointers are used - Faults if a signature doesn't match (tampering detected)
Why This Matters¶
Apple Silicon includes hardware Pointer Authentication that makes ROP attacks cryptographically expensive. PAC signs every return address and function pointer, making exploitation extremely difficult even with full memory corruption.
Cryptographic Protection¶
PAC uses hardware cryptography:
Without PAC:
Stack: [...][ret_addr][...]
Attacker overwrites ret_addr
Function returns to attacker's address
With PAC:
Stack: [...][signed_ret_addr][...]
signature = QARMA(ret_addr, context, secret_key)
Attacker overwrites ret_addr
Signature verification fails
CPU faults → crash instead of exploitation
Why PAC Is Stronger Than Canaries¶
| Protection | Mechanism | Bypass |
|---|---|---|
| Stack canary | Random value | Info leak reveals canary |
| PAC | Cryptographic signature | Requires key extraction (impossible) |
Apple Silicon PAC Implementation¶
| Chip | PAC Support |
|---|---|
| M1/M1 Pro/Max | Full |
| M2/M2 Pro/Max | Full |
| M3/M3 Pro/Max | Full |
| A12+ | Full (iOS) |
arm64 vs arm64e¶
| Architecture | PAC | Status |
|---|---|---|
| arm64 | No | Standard, widely compatible |
| arm64e | Yes | Enhanced security, Apple Silicon |
arm64e enables PAC instructions.
Context Binding¶
PAC signatures include context:
Signature = f(pointer, context, key)
Context examples:
- Stack pointer (for return addresses)
- Type information
- Object pointer
Reusing a signed pointer in wrong context = verification failure
Performance¶
| Operation | Overhead |
|---|---|
| Sign pointer | 1-2 cycles |
| Verify pointer | 1-2 cycles |
| Overall app | <1% |
Hardware implementation is extremely fast.
iOS Deployment¶
| iOS Version | PAC Status |
|---|---|
| iOS 12+ | Kernel uses PAC |
| iOS 14+ | More userspace PAC |
| iOS 15+ | Widespread PAC |
- Hardware-enforced protection: Cannot be bypassed by software
- ROP mitigation: Return addresses cannot be reliably overwritten
- JOP mitigation: Function pointers are protected
- Apple Silicon native: Full support on M1/M2/M3 chips
Performance Considerations¶
PAC on Apple Silicon is extremely efficient:
| Metric | Impact |
|---|---|
| Runtime overhead | <1% |
| Sign/verify cost | 1-2 cycles |
| Memory overhead | None |
| arm64e overhead vs arm64 | Negligible |
Why Apple Silicon PAC is fast: - Dedicated cryptographic hardware in the CPU - Signing/verification happens in parallel with other operations - No memory accesses required - Optimized for the common case (no tampering)
Benchmark data:
| Workload | arm64 | arm64e | Difference |
|---|---|---|---|
| Compute-heavy | 100% | 100.3% | <0.5% |
| Call-heavy | 100% | 101% | ~1% |
| Real apps | 100% | 100.5% | <1% |
Resolution¶
Targeting arm64e¶
The arm64e architecture enables PAC. Standard arm64 does not.
Xcode:
- Select your target
- Go to Build Settings → Architectures
- Add
arm64eto Architectures
Command Line:
CMake:
Using Pointer Authentication Intrinsics¶
For explicit pointer signing:
#include <ptrauth.h>
// Sign a function pointer
void (*signed_ptr)(void) = ptrauth_sign_unauthenticated(
func_ptr,
ptrauth_key_function_pointer,
0
);
When to Suppress¶
This rule may be suppressed for:
- Compatibility requirements: Need to run on older hardware
- Third-party code: Libraries not compiled for arm64e
- Universal binaries: Supporting both arm64 and arm64e
Important Notes¶
arm64ebinaries only run on Apple Silicon- Universal binaries can contain both
arm64andarm64eslices - iOS has limited support for third-party arm64e binaries
- PAC is different from ARM BTI (Branch Target Identification)