Pointer Authentication and Memory Tagging
All about ARM security extensions
Pointer Authentication
Background
- Code reuse attacks: ROP,JOP
- Memory protection largely prevents code injection
- Various mitigations today
- e.g. ASLR, execute-only memory, CFI, canaries, pointer mangling, shadow stacks
- difficult to integrate
- non-trivial performance / code size impact
- inhibit debugging
ROP protection example
backwards compatible ver.
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
normal ver.
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
Theory
- instructions to sign and authenticate pointers
- architecture provides mechanism, not policy
- Pointer Authentication Code (PAC)
- authentication metadata stored within pointer
- no additional space required
- derived from:
- A pointer value
- A 64-bit context value
- A 128-bit secret key
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
- Key:
- 128-bit value inhibit prediction / forging of PACs
- APIAKEY can be used, but not read/written at EL0 (userspace)
- The kernel maintains an APIAKey value for each process (shared by all threads within), which is initialised to a random value at exec() time.
- limited risk of disclosure / modification
- five separate keys:
- two for executable (instruction) pointers
- two for data
- one "general" key
- Pointer Memory layout:
- 7 bits with 48-bit VA with tagging
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
- 15 bits with 48-bit VA without tagging
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
- Operations:
- sign
- PAC* instructions sign pointers with PACs
- Result is not a usable pointer
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
- authenticate
- AUT* instructions authenticate PACs
- If PAC matches, result is the original pointer
- If PAC doesnβt match, result is an invalid pointer β faults upon use
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
- strip
- XPAC* instructions strip PACs
- Result is the original pointer
- No authentication is performed
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
Mechanism
- Insert a PAC into a pointer
- Strip a PAC from a pointer
- Authenticate strip a PAC from a pointer
- If authentication succeeds, the code is removed, yielding the original pointer
- If authentication fails, bits are set in the pointer such that it is guaranteed
to cause a fault if used
Usage
- Optional ARMv8.3-A extension
- Detects illicit modification of pointers (and data structures)
- Backwards compatible subset
- binaries using some features can run on any ARMv8-A CPU (without protection)
- distributions only need one set of binaries
Memory Tagging
- "Hardware-ASAN on steroids"
- RAM overhead: 3%-5%
- CPU overhead: (hoping for) low-single-digit %
- AArch64 only because it need Top Byte Ignore(TBI)
- In 64-bit, general-purpose registers(GPR64) make the most significant 16 bits of an address must be all 0xFFFF or 0x0000
- the top eight bits, that is [63:56] of the Virtual Address are ignored by the processor when tagged addressing support is enabled
- Two types of tags
- Every aligned 16 bytes of memory have a 4-bit tag stored separately
- Every pointer has a 4-bit tag stored in the top byte
Mechanism
- Allocation:
- Align allocations by 16
- Choose a 4-bit tag (random is ok)
- Tag the pointer
- Tag the memory (optionally initialize it at no extra cost)
- Deallocation:
- Re-tag the memory with a different tag
- To use tagging with heap allocations only the allocator needs to make use of the new instructions, the rest of the code only performs standard LDR/STR
Detect
-
Heap-buffer-overflow
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
-
Heap-use-after-free
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
Kernel ABI and HWCAPs
- On AArch64 the TCR_EL1.TBI0 bit is set by default(CPU Feature Register)
- All syscalls need to accept any valid tagged pointer, and it should work as the untagged pointer.
- UB for invalid tagged pointer
- Documentation/arm64/tagged-address-abi.rst
MTE Enabled Kernel Interface
- built on top of the newly introduced Aarch64 Tagged Address ABI
- The Kernel exposes a new mmap()/mprotect() flag: PROT_MTE
- Kernel supports both the exception types: Precise and Imprecise
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
- How does it work?
- Memory allocator, which ultimately invokes mmap()
- with a special flag, PROT_MTE, the reserved memory has tagging effects enabled
- The allocator tags the memory and returns to the application a tagged pointer
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
Compiler perspective(challenges)
- slide1
- C family has suck memory safety
- Use-after-free / buffer-overflow / uninitialized memory
- High and Critical ratio in bugs
- AddressSanitizer (ASAN) is not enough
- Hard to use in production
- Not a security mitigation
- Tagging heap objects
- CPU: malloc/free become O(size) operations
- Tagging stack objects
- CPU: function prologue becomes O(frame size)
- Stack size: local variables aligned by 16
- Code size: extra instructions per function entry/exit
- Register pressure: local variables have unique tags, not as simple as [SP, #offset]
- Malloc zero-fill
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
Image Not Showing
Possible Reasons
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More β
- reduce the overhead
existing implementations
- SPARC ADI
- HW ASAN
- 4-bit tags per 64-bytes of memory
- high RAM overhead due to 64-byte alignment
- LLVM HWASAN
- Software implementation similar to ASAN (LLVM ToT)
- 8-bit tags per 16-bytes of memory
- AArch64-only (uses top-byte-ignore)
- Overhead: 6% RAM, 2x CPU, 2x code size