Skip to content

AD3017: EnableArmBTI

Summary

Property Value
ID AD3017
Name EnableArmBTI
Category Security
Severity Warning
Applies to ELF (Linux/Unix) - AArch64

Description

This rule checks that AArch64 ELF binaries have ARM Branch Target Identification (BTI) enabled. BTI is a hardware security feature that protects against Jump-Oriented Programming (JOP) and Call-Oriented Programming (COP) attacks.

Why This Matters

ARM BTI is the ARM ecosystem's answer to control-flow hijacking attacks. As ARM processors become dominant in mobile, embedded, and increasingly server environments, BTI provides essential protection against JOP and COP attacks.

ARM in Critical Infrastructure

ARM processors are everywhere:

Domain Examples
Mobile All modern smartphones
Cloud AWS Graviton, Ampere
Embedded IoT, automotive
Apple M1/M2/M3 Macs
Windows Snapdragon PCs

Securing ARM binaries is increasingly critical.

JOP/COP on ARM

ARM has rich indirect branch instructions:

blr x0    ; Branch and Link to register (indirect call)
br x1     ; Branch to register (indirect jump)
ret       ; Return (special case of BR x30)

Without BTI, attackers can redirect any of these to arbitrary code.

How BTI Works

Without BTI:
  blr x0 → Can branch to ANY instruction

With BTI:
  blr x0 → Target MUST be BTI instruction
           Otherwise → exception

BTI variants:
  bti c   ; Valid target for BLR (calls)
  bti j   ; Valid target for BR (jumps)
  bti jc  ; Valid for both calls and jumps

Gadget Elimination

Normal binary:
  Every instruction is potential gadget landing
  Millions of possible targets

BTI-enabled binary:
  Only BTI instructions are valid targets
  Compiler controls where these appear
  Dramatically reduced attack surface

BTI Instruction Overhead

Scenario Overhead
Indirect call targets One BTI instruction (4 bytes)
Function pointers BTI at each target
Virtual methods BTI in vtable targets
Overall 1-3% code size, minimal runtime

Hardware Support

Processor BTI Support
ARM Cortex-A78+ Yes
ARM Neoverse N1+ Yes
Apple M1+ Yes (called BTI/PAC)
Qualcomm Snapdragon 8+ Yes

Backward Compatibility

BTI instructions execute as NOPs on older hardware:

On BTI-enabled CPU:
  - BTI instructions enforced
  - Invalid targets cause exception

On older CPU:
  - BTI instructions execute as NOP
  - No protection, but code works
  - Safe for mixed deployment
  • JOP/COP protection: BTI restricts where indirect branches can land
  • Hardware enforcement: Uses CPU features for control-flow protection
  • Landing pad validation: Only BTI instructions are valid targets for indirect branches
  • ARM ecosystem: Standard security feature on modern ARM64 platforms

How BTI Works

When BTI is enabled: 1. Each valid indirect branch target must begin with a BTI instruction 2. The BTI instruction specifies which types of branches are allowed (call, jump, or both) 3. If an indirect branch lands elsewhere, the CPU raises an exception 4. This significantly reduces the gadgets available to attackers

Performance Considerations

BTI has negligible runtime overhead due to hardware implementation:

Metric Impact
Runtime overhead <0.5% typical
Code size increase 1-3% (BTI instructions)
Memory overhead None

Why BTI is nearly free: - BTI instructions are effectively NOPs on the normal execution path - Hardware validation happens during instruction fetch - No additional memory accesses or pipeline stalls

Comparison with software CFI:

Protection Overhead Precision
BTI (hardware) <0.5% Function-level
Software CFI 5-20% Type-level possible

Combined with PAC: Using -mbranch-protection=standard enables both BTI and PAC with approximately 1-2% total overhead for comprehensive protection.

How to Fix

Compile with branch protection

# Enable BTI
gcc -mbranch-protection=bti -o myapp myapp.c

# Enable both BTI and PAC (recommended)
gcc -mbranch-protection=standard -o myapp myapp.c

# Clang equivalent
clang -mbranch-protection=bti+pac-ret -o myapp myapp.c

Verify the fix

readelf -n myapp | grep -i "BTI"
# Should show BTI in properties

# Or check for BTI instructions in disassembly
objdump -d myapp | grep -c "bti"

Example

Fail: Binary does not have BTI enabled

# No BTI property in ELF notes

Pass: Binary has BTI enabled

Properties: AArch64 feature: BTI, PAC

Requirements

  • Compiler: GCC 9+ or Clang 8+
  • CPU: ARMv8.5-A or later (with FEAT_BTI)
  • Kernel: Linux 5.8+ for BTI support
  • glibc: 2.32+ for full support

See Also