Skip to content

AD5003: EnableStackProtectorMachO

Summary

Property Value
ID AD5003
Name EnableStackProtectorMachO
Category Security
Severity Error
Applies to Mach-O (macOS/iOS)

Description

Stack protector adds a 'canary' value between local variables and the return address on the stack. If a buffer overflow overwrites the canary, the program will detect this and abort before the corrupted return address is used.

Enable this protection by compiling with -fstack-protector-strong or -fstack-protector-all.

How It Works

The rule checks for the presence of stack canary symbols:

  • __stack_chk_fail
  • __stack_chk_guard
  • ___stack_chk_fail
  • ___stack_chk_guard

These symbols indicate stack protector is enabled and linked.

Why This Matters

Stack canaries are one of the most effective and widely-deployed exploit mitigations on Apple platforms. They detect stack buffer overflows before the attacker can hijack control flow, converting potential code execution into a controlled crash.

How Stack Canaries Work on macOS

Stack Layout with Canary:

  ┌─────────────────┐  High address
  │  Return Address │  ← Attacker target
  ├─────────────────┤
  │  Saved RBP      │
  ├─────────────────┤
  │  CANARY VALUE   │  ← Random, checked on return
  ├─────────────────┤
  │  Local buffer   │  ← Overflow starts here
  └─────────────────┘  Low address

Overflow must corrupt canary to reach return address.
Canary mismatch = __stack_chk_fail = abort()

Protection Levels

Flag Protection Overhead Recommendation
-fstack-protector Functions with buffers Low Legacy
-fstack-protector-strong More functions Low Recommended
-fstack-protector-all All functions Higher High security

Apple Defaults

Platform Default
Xcode iOS -fstack-protector-strong
Xcode macOS -fstack-protector-strong
Command line Must specify

Canary Implementation

macOS uses __stack_chk_guard:

__stack_chk_guard:
  - Random value at process start
  - Contains terminator bytes (\0, \n, etc.)
  - Hard to include in overflow payload

Attack Difficulty

Scenario Without Canary With Canary
strcpy overflow Code execution Crash
sprintf overflow Code execution Crash
Off-by-one May succeed Usually crash
Info leak needed No Yes (to bypass)

Performance

Level Overhead
-fstack-protector <1%
-fstack-protector-strong ~1%
-fstack-protector-all 2-5%
  • Buffer overflow detection: Catches stack smashing at runtime
  • Controlled abort: Crashes safely instead of executing attacker code
  • Low overhead: Minimal performance impact with -fstack-protector-strong
  • Apple default: Enabled by default in Xcode for most project types

Resolution

Xcode

Stack protector is enabled by default. Ensure it hasn't been disabled:

  1. Select your target in Xcode
  2. Go to Build SettingsApple Clang - Code Generation
  3. Ensure Enable Stack Canaries is set to Yes

Command Line (Clang)

# Recommended - protects most vulnerable functions
clang -fstack-protector-strong source.c -o binary

# Maximum protection - all functions
clang -fstack-protector-all source.c -o binary

CMake

add_compile_options(-fstack-protector-strong)

When to Suppress

This rule may be suppressed for:

  • Performance-critical code: After profiling shows significant impact
  • Freestanding code: Kernel extensions without libc
  • Swift-only code: Swift has its own memory safety guarantees
  • AD3003 - ELF version of this check
  • AD5008 - Additional stack protection via SafeStack

References