MemTagSanitizer

Introduction

Note: this page describes a tool under development. Part of thisfunctionality is planned but not implemented. Hardware capable ofrunning MemTagSanitizer does not exist as of Oct 2019.

MemTagSanitizer is a fast memory error detector and a code hardeningtool based on the Armv8.5-A Memory Tagging Extension. Itdetects a similar class of errors as AddressSanitizer or HardwareAssistedAddressSanitizer, but withmuch lower overhead.

MemTagSanitizer overhead is expected to be in low single digits, bothCPU and memory. There are plans for a debug mode with slightly highermemory overhead and better diagnostics. The primary use case ofMemTagSanitizer is code hardening in production binaries, where it isexpected to be a strong mitigation for both stack and heap-basedmemory bugs.

Usage

Compile and link your program with -fsanitize=memtag flag. Thiswill only work when targeting AArch64 with MemTag extension. Onepossible way to achieve that is to add -targetaarch64-linux -march=armv8+memtag to compilation flags.

Implementation

See HardwareAssistedAddressSanitizer for a general overview of atag-based approach to memory safety. MemTagSanitizer follows asimilar implementation strategy, but with the tag storage (shadow)provided by the hardware.

A quick overview of MTE hardware capabilities:

  • Every 16 aligned bytes of memory can be assigned a 4-bit Allocation Tag.
  • Every pointer can have a 4-bit Address Tag that is in its most significant byte.
  • Most memory access instructions generate an exception if Address Tag != Allocation Tag.
  • Special instructions are provided for fast tag manipulation.

Stack instrumentation

Stack-based memory errors are detected by updating Allocation Tag foreach local variable to a random value at the start of its lifetime,and resetting it to the stack pointer Address Tag at the end ofit. Unallocated stack space is expected to match the Address Tag ofSP; this allows to skip tagging of any variable when memory safety canbe statically proven.

Allocating a truly random tag for each stack variable in a largefunction may incur significant code size overhead, because it meansthat each variable’s address is an independent, non-rematerializablevalue; thus a function with N local variables will have extra N livevalues to keep through most of its life time.

For this reason MemTagSanitizer generates at most one random tag perfunction, called a “base tag”. Other stack variables, if there areany, are assigned tags at a fixed offset from the base.

Please refer to this document)for more details about stack instrumentation.

Heap tagging

Note: this part is not implemented as of Oct 2019.

MemTagSanitizer will use Scudo Hardened Allocatorwith additional code to update memory tags when

  • New memory is obtained from the system.
  • An allocation is freed.

There is no need to change Allocation Tags for the bulk of theallocated memory in malloc(), as long as a pointer with the matchingAddress Tag is returned.

More information