Introduction

Memory bugs such as heap-buffer-overflow and heap-use-after-free are often exploited by malicious actors to perform actions that may leak sensitive user data or disrupt the functioning of the software. These bugs are common in languages with no automatic memory management like C and C++.

Memory tagging is a technique included in the Arm ISA v8.5 specification to improve memory safety by associating a ‘tag’ with allocated memory blocks.

  • The tag is applied to the memory block and to the pointer variable holding the address of the memory block.

  • Pointers use ‘address tags’ that are stored in the top 4 bits of every pointer used in the process.

  • For memory blocks, each granule i.e. a 16-byte region is annotated with a 4-bit tag referred as a ‘memory tag’. Logically, every 16 bytes of memory now contain an extra 4 bits of metadata in addition to 128 bits of data.

Working

The following describes how memory tags are modified during memory operations:

  • Allocation: The operating system assigns a random tag to the allocated memory block and to the pointer holding the address of the block.

  • Access: For all subsequent read and write operations, the tag stored within pointer/address in matched against the tag assigned to the memory block. If the tags do not match, the CPU signals the operating-system and operation is blocked immediately (via a SIGSEV) or reported asynchronously.

  • Deallocation: The operating-system changes the tag of the allocated memory block and marks it as ‘free’ for further allocations.

Preventing Memory Bugs - Examples

Heap Buffer Overflow

ptr is assigned the tag A and the corresponding memory block is assigned the same tag. When trying to access a memory location outside the allocated block i.e. ptr[32] the tags of the ptr A and that of the memory location, E, mismatch, leading to a SIGSEV.

Heap Use After Free

ptr and the corresponding memory block are assigned the tag D. When deallocating the memory block i.e. calling free(ptr), the tag of memory block is changed from D to 4. Now, if the memory block is access with ptr for ex. with ptr[16], the tags mismatch and the access is refused by the operating-system.

Comparison with Address Sanitizer

Address Sanitizer, commonly referred as Asan, is another technique that protects a program against illegal memory accesses at runtime. When Asan is attached/embedded into the program, each memory allocation is surrounded by guard-rails that are blocks of memory managed by Asan.

Asan generally takes up more memory than memory-tagging as it uses additional memory-blocks as red-zones (guard-rails).

Here’s an excellent blog to understand how Address Sanitizer works: https://suelan.github.io/2020/08/18/20200817-address-sanitizer/#Heap-buffer-overflow

References