AddressSanitizer, Hardware ASAN, MTE
AddressSanitizer это популярный инструмент для поиска проблем с памятью, однако у него есть ряд недостатков:
- Оверхед по использованию памяти (1.5-3x) и CPU (1.5-3x);
- Не поддерживает инструментацию ассемблерного кода;
- Не поддерживает выявление проблем в сборках без доступа к исходному коду;
- Не поддерживает выявление проблем при доступе невалидной памяти в юзерспейсе из ядра;
Перечисленные недостатки не мешают использованию санитайзера, если его использование ограничено тестовыми средами, а вот для использования в продакшене замедление скорости и повышенное потребление памяти может быть неприемлимо. Мой интерес к HWASAN вызван тем, что AddressSanitizer нельзя полноценно использовать для фаззинга LuaJIT, потому что часть кода написана вручную на ассемблере, а ASAN инструментирует только C/C++ код.
В статье “Memory Tagging and how it improves C/C++ memory safety” авторы описывают использование ASAN для предрелизных сборок браузера Chrome:
Despite our large-scale efforts for fuzzing the Chrome browser we keep finding memory safety bugs in the shipped versions of Chrome. A version of Chrome with SyzyASAN instrumentation used by a small subset of real users on Windows (so-called “canary channel”) finds two-three bugs every week (not all of these bugs are public, the total number after 5 years of testing is ~950). The majority of these bugs are heap-use-after-free (SyzyASAN does not find stack-related bugs). These are the bugs that happen when real users use the Chrome browser normally, i.e. not necessarily when someone is trying to attack it. There is a skew towards bugs that require complicated user interaction, since other kinds of bugs are more often detected during testing & fuzzing. Shipping such instrumented builds to more users leads to more bugs discovered per month.
SyzyASAN https://blog.chromium.org/2013/05/testing-chromium-syzyasan-lightweight.html
и в той же статье использование ASAN для Android:
Last but not least, the Android platform has adopted ASAN as the main memory sanitization tool, replacing the slower Valgrind. However, ASAN’s overhead continues to be problematic. For one, Android typically runs dozens of concurrent processes (“Android apps” and services) on constrained devices. At that point, the combined memory overhead starts to negatively affect the performance often making devices unusable. Besides, ASAN requires specially-built libraries, which usually overflow the limited system storage of Android devices, necessitating a non-standard directory layout that complicates practical use outside of a development environment. Even with these constraints, ASAN has been very successful in finding platform and app issues.
До июля 2025 года Mozilla собирала ночные сборки Firefox с включенным ASAN (https://firefox-source-docs.mozilla.org/tools/sanitizer/asan_nightly.html), а теперь ASAN заменили на Probabilistic Heap Checker (aka GWIP ASAN). (см. https://bugzilla.mozilla.org/show_bug.cgi?id=1523268):
The ASan Nightly build only comes with a slight slowdown at startup and browsing, sometimes it is not even noticeable. The RAM consumption however is much higher than with a regular build. Be prepared to restart your browser sometimes, especially if you use a lot of tabs at once. Also, the updates are larger than the regular ones, so download times for updates will be higher, especially if you have a slower internet connection.
Есть альтернативная реализация санитайзера для памяти - HWASAN. HWAddressSanitizer which uses pointer-masking to implement the idea explained above. Проблема в том, что для его использования требуется поддержка Memory Tagging в CPU. Игнорируя поговорку “лучшее - враг хорошего” я хотел попробовать HWASAN совместно с фаззингом и первая попытка была несколько лет назад, когда был доступ к AWS Graviton. Тогда никаких интересных результатов получить не удалось, никаких новых проблем я не нашел. После WWDC25 я наткнулся на статью от инженеров Apple “Memory Integrity Enforcement: A complete vision for memory safety in Apple devices” (https://security.apple.com/blog/memory-integrity-enforcement/) и вспомнил про HWASAN. Мне стало интересно узнать стал ли HWASAN более доступен для использования. В этой заметке расскажу, что получилось выяснить.
HWASAN https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
HWASAN relies on Address Tagging which is only available on AArch64. For other
64-bit architectures it is possible to remove the address tags before every
load and store by compiler instrumentation, but this variant will have limited
deployability since not all of the code is typically instrumented. On x8664,
HWASAN utilizes page aliasing to place tags in userspace address bits.
Currently only heap tagging is supported. The page aliases rely on shared
memory, which will cause heap memory to be shared between processes if the
application calls fork(). Therefore x8664 is really only safe for applications
that do not fork.
HWASAN detects against spatial and temporal memory errors; i.e. you have a pointer to memory that gets freed, and use it again (temporal), or a stack overrun into nearby memory (spatial).
Pointer Authentication is used to sign pointers to give them a kind of provenance, but it’s largely used to protect against code reuse/control flow attacks (ROP is much more difficult because you cannot re-use arbitrary gadgets in the executable; the stack pointer is part of the pointer signature, so screwing with it results in termination if the signature doesn’t check out.)
They are both complimentary; you could use them both. HWASAN (using memory tagging) and pointer authentication use the unused upper bits of a virtual address to store their metadata. They are compatible, but this does mean combining them reduces the overall amount of bits available for pointer signatures.
There is a recent paper discussing the use of pointer authentication to build more advanced defenses; it looks like it’s worth a read, and some comparisons (including HWASAN) are available in Section 8: https://www.usenix.org/system/files/sec19fall_liljestrand_prepub.pdf
It is theoretically possible to implement HWASAN on architectures that do not
have top-byte-ignore using page aliasing (mmap(MAP_SHARED)) to store the
address tag in the meaningful address bits. However our experiments indicate
that such implementation would be impractical due to huge stress on the TLB.
У HWASAN оверхед по CPU ~2x и оверхед по RAM ? 6% RAM, 2x CPU, 2x code size
AArch64
В этой публикации представлен перевод вступительной части документа (whitepaper) о новом расширении Armv8.5-A: Memory Tagging Extension (MTE) от компании ARM. MTE стремится повысить безопасность кода, написанного на небезопасных языках, не требуя изменения исходного кода, а в некоторых случаях, и не требуя перекомпиляции. Простое развертывание механизмов обнаружения и предотвращения последствий нарушений безопасности памяти могут предотвратить эксплуатацию большого класса уязвимостей.
MTE is an Armv9 feature that uses hardware to provide fine-grained memory protection, unlike software-only solutions.
Optional extension in ARMv9, announced Aug 2018.
https://docs.kernel.org/arch/arm64/memory-tagging-extension.html
ARMv8.5 based processors introduce the Memory Tagging Extension (MTE) feature. MTE is built on top of the ARMv8.0 virtual address tagging TBI (Top Byte Ignore) feature and allows software to access a 4-bit allocation tag for each 16-byte granule in the physical address space. Such memory range must be mapped with the Normal-Tagged memory attribute. A logical tag is derived from bits 59-56 of the virtual address used for the memory access. A CPU with MTE enabled will compare the logical tag against the allocation tag and potentially raise an exception on mismatch, subject to system registers configuration.
Armv8.5-A incorporates a new feature called Memory Tagging. When Memory Tagging is in use, a tag is assigned to each memory allocation. All accesses to memory must be made via a pointer with the correct tag. Use of an incorrect tag is noted and the operating system can choose to report it to the user immediately, or to note the process in which it occurred, for later investigation.

For instance, in the diagram below the access to the memory at 0x8000 will work
because the pointer, used to make access, has the same tag (represented by a
color) as the memory being accessed. However, the access to 0x9000 will fail,
because the pointer has a different tag to the memory.
Memory Tagging can be used in a number of scenarios. During development, it can be used to detect memory errors in the test environment. Following deployment of an application, it can be used to detect issues in the field, and to provide feedback to the developer. Once feedback has been received, vulnerabilities can be analyzed and addressed before they are exploited by an attacker.
https://habr.com/ru/articles/493118/ https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/enhancing-memory-safety
https://security.googleblog.com/2019/08/adopting-arm-memory-tagging-extension.html
https://www.kernel.org/doc/Documentation/arm64/tagged-pointers.txt
- Краткий обзор Memory Tagging Extension (Armv8.5-A), https://habr.com/ru/articles/493118/
- AArch64 HWASAN (TG=16, TS=8).
- The ARM v8.3-A specification introduced Pointer Authentication in 2016.
- https://blog.ret2.io/2021/06/16/intro-to-pac-arm64/
- ARMv8.3 Pointer Authentication, https://events.static.linuxfound.org/sites/events/files/slides/slides_23.pdf
- LLVM: https://reviews.llvm.org/D64169 https://llvm.org/devmtg/2019-10/slides/McCall-Bougacha-arm64e.pdf https://llvm.org/devmtg/2018-10/slides/Serebryany-Stepanov-Tsyrklevich-Memory-Tagging-Slides-LLVM-2018.pdf https://llvm.org/devmtg/2020-09/slides/Stepanov-Memory_tagging_in_LLVM_and_Android.pdf
- Android, https://security.googleblog.com/2019/08/adopting-arm-memory-tagging-extension.html
- Android, https://developer.android.com/ndk/guides/arm-mte
- How it works on Pixel 8, https://googleprojectzero.blogspot.com/2023/11/first-handset-with-mte-on-market.html
- Linux kernel, https://lkml.org/lkml/2019/7/23/728 https://docs.kernel.org/arch/arm64/memory-tagging-extension.html https://lpc.events/event/4/contributions/571/attachments/399/642/MTE_LPC.pdf
;login https://www.usenix.org/system/files/login/articles/login_summer19_03_serebryany.pdf
Memory Safety: How Arm Memory Tagging Extension Addresses this Industry-wide Security Challenge, https://newsroom.arm.com/blog/memory-safety-arm-memory-tagging-extension
Through the second-generation Armv9 CPUs announced in June 2022, we introduced a brand-new Asymmetric MTE, which offers improved flexibility between the speed, precision, and targeting of these security vulnerabilities. This benefits software development with more stable applications, while also enabling a broader rollout of MTE across the ecosystem. Chipsets that adopt Arm Cortex-X3, Cortex-A715 and the newly updated version of Cortex-A510 (A510-r1) CPUs will have asymmetric MTE built in.
- Apple:
Версии ПО
Для полноценного использования MTE требуется во всех компонентах ОС и тулчейна:
Поддержка в GLibc в версиях 2.38+, выключена по умолчанию, для включения нужно
использовать export GLIBC_TUNABLES=glibc.mem.tagging=3.
Поддержка в QEMU в версиях 8.1.0+, см. https://www.qemu.org/2023/08/22/qemu-8-1-0/.
Поддержка в Linux-ядре в версиях 5.10+, требуется включение опции
CONFIG_ARM64_MTE, см.
https://docs.kernel.org/arch/arm64/memory-tagging-extension.html
Для сборки с помощью LLVM нужно использовать опции
-fsanitize=memtag-[stack|heap|globals] и указать AArch64 c MTE в качестве
целевой системы чтобы компилятор вставил инструкции для управления метками
адресов памяти во время выделения памяти, освобождения и использования во время
доступа к памяти. Флаг -fsanitize-memtag-mode позволяет выбрать режим
(синхронный или асинхронный). llvm-readelf может показать информацию о
поддержке MTE с помощью опции --memtag.
Поддержка в GDB добавлена в версиях начиная с 11.1, https://sourceware.org/gdb/current/onlinedocs/gdb.html/Memory-Tagging.html, https://lists.gnu.org/archive/html/info-gnu/2025-01/msg00009.html.
Intel x86_64
Intel LAM
- добавили поддержку в ядро Linux 6.4, август 2022 (https://lore.kernel.org/all/20220815041803.17954-1-kirill.shutemov@linux.intel.com/) https://www.phoronix.com/news/Intel-LAM-Merged-Linux-6.4 https://lpc.events/event/11/contributions/1010/attachments/875/1679/LAM-LPC-2021.pdf
- выключили по умолчанию в ядре Linux 6.12-rc5, https://www.phoronix.com/news/Linux-Disabling-Intel-LAM
- LLVM, https://reviews.llvm.org/D132467
- GCC 13, https://gcc.gnu.org/pipermail/gcc-patches/2022-November/605691.html
- RISC-V, расширение zjpm, https://github.com/riscv/riscv-j-extension/blob/5c65338c302647f52f4f42c5b3dbbc4d6db6edd4/zjpm-spec.pdf https://github.com/riscv/riscv-memory-tagging LLVM, https://github.com/llvm/llvm-project/issues/150102
Sparc
- SPARC ADI (TG=64, TS=4)
- CPU: SPARC M7/M8
Exists in real hardware since ~2016 (SPARC M7/M8 CPUs) - 4-bit tags per 64-bytes of memory - Great, but high RAM overhead due to 64-byte alignment
https://www.oracle.com/technetwork/database/bi-datawarehousing/sas/con8216-final-2760803.pdf
Заключение
xxx
Ссылки
- “Memory Tagging and how it improves C/C++ memory safety”, https://arxiv.org/pdf/1802.09517