Hi,
I need some feedback/discussion on GCC/Binutils command line options
around MTE
tagged stack usage. See "Proposed GCC/Binutils implementation for the user
space ABI for MTE stack" below in the email for the high-level design.
Thanks
Indu
---------
MTE Background
--------------
Memory Tagging Extension (MTE) is an AArch64 extension. This extension
allows coloring of 16-byte memory granules with 4-bit tag values. The
extension provides additional instructions in ISA and a new memory type,
Normal Tagged Memory, added to the Arm Architecture. This hardware-assisted
mechanism can be used to detect memory bugs like buffer overrun or
use-after-free. The detection is probabilistic.
Current glibc and kernel support
--------------------------------
A user program may exercise MTE on stack, heap and/or globals data accesses.
The applicable memory range must be mapped with the Normal-Tagged memory
attribute ([1]). When available and enabled, the kernel advertises the
feature to userspace via HWCAP2_MTE. The new flag PROT_MTE (for mmap () and
mprotect ()) specify that the associated pages allow access to the MTE
allocation tags.
glibc currently provides a tunable glibc.mem.tagging ([3]) and MTE aware
malloc. The tunable can be used to enable the malloc subsystem to allocate
tagged memory with either precise or deferred faulting mode. The GNU C
Library startup code will automatically enable memory tagging support in the
kernel if this tunable has any non-zero value.
User space ABI for MTE enable stack usage
------------------------------------------
As per the Memtag ABI Extension to ELF for the ArmĀ® 64-bit Architecture
(AArch64) ([5]), the first two of the following dynamic tags are of interest
(as we are interested in stack tagging ATM):
DT_AARCH64_MEMTAG_MODE
DT_AARCH64_MEMTAG_STACK
DT_AARCH64_MEMTAG_GLOBALS
AFAICT, these are not implemented in the Linux kernel nor specified in glibc
yet.
Proposed GCC/Binutils implementation for the user space ABI for MTE stack
--------------------------------------------------------------------
1. Generating DT_AARCH64_MEMTAG_MODE
GCC
---
Add new GCC command line option: -fsanitize-memtag-mode=<mode> where mode is
one of:
- none
- sync
- async
This option does not affect code generation. The driver simply passes
this to
the linker by using the --aarch64-memtag-mode=<mode> ld option. IOW,
this is
a convenience command line option which equivalent to
-Wl,--aarch64-memtag-mode=<mode>.
No configure time checks will be added on the GCC side. If the linker does
not support --aarch64-memtag-mode=<mode>, user will see an error right away
anyway.
Binutils
--------
Add new ld command line option for emultempl/aarch64elf :
--aarch64-memtag-mode=<mode> where <mode> can be one of none, sync, or
async.
For mode of sync or async, a DT_AARCH64_MEMTAG_MODE dynamic tag with a
value of
0 or 1 respectively is emitted.
Q: Why does the MemTagABI ([5]) not assign a value for asymm mode yet?
Generated only for aarch64 elf. Linker silently ignores when specified for
32-bit elf. As per the MemtagABI doc, the dynamic tag when present on a
dynamically loaded objects, is ignored.
readelf displays the dynamic tag when present.
2. Generating DT_AARCH64_MEMTAG_STACK
GCC
---
In the RFC patch set I sent earlier ([4]), I used the new option
-fsanitize=memtag and was thinking that we will use params to control
whether
stack or globals are colored. E.g., with
--param=memtag-instrument-stack=1 or
--param=memtag-instrument-globals=1. But this will not work because the
driver
will have no visibility of the params.
So, a new GCC command line option: -fsanitize=memtag-stack should instead be
used to tag stack variables of a function. This option will trigger the
driver
to pass --aarch64-memtag-stack to the linker, if linking. (Later, for
globals,
we can use -fsanitize=memtag-globals in GCC and --aarch4-memtag-globals
in ld.)
Binutils
-------
Add new ld command line option for emultempl/aarch64elf :
--aarch64-memtag-stack
GNU ld will emit a DT_AARCH64_MEMTAG_STACK dynamic tag with a value of
1 if --aarch64-memtag-stack is specified.
Generated only for aarch64 elf. Linker silently ignores when specified for
32-bit elf. As per the MemtagABI doc, the dynamic tag when present on a
dynamically loaded objects, is ignored.
Q: Should it be --aarch64-memtag=<item> instead, where <item> is either
<stack>
or <globals> ?
Q: It may be useful to validate that all components being linked have been
compiled with -fsanitize=memtag-stack. WDYT ? If we need to validate, we
will
likely need a new assembler directive, and find a way to convey the
information
to the linker. Thoughts ?
Q: Should ld warn if it sees some EH Frame info with augmentation char
'G' but
no --aarch64-memtag-stack in the command line by the user ?
readelf displays the dynamic tag when present.
3. Generating .cfi_mte_memtag_frame CFI direcive
GCC
----
GCC will emit a .cfi_mte_memtag_frame (LLVM already uses this CFI directive)
after a .cfi_startproc if:
- memtag sanitizer for stack is enabled, and
- the function has non-zero stack vars colored via MTE insns.
If the available assembler does not support the new
.cfi_mte_memtag_frame, users will see build time failures:
gcc -c temp.c -fsanitize=memtag-stack -march=armv8.5-a+memtag
XX.s: Assembler messages:
XX.s:NN: Error: unknown pseudo-op: `.cfi_mte_tagged_frame'
Q: Perhaps backporting the .cfi_mte_memtag_frame support in GAS to a
few previous releases is the only thing that can be done ?
Binutils
--------
The GNU assembler will emit an augmentation char 'G' in the DWARF / EH Frame
FDE, and the linker will merge FDEs under a parent CIE as necessary while
taking the augmentation char 'G' into account.
References:
[1] Memory Tagging Extension (MTE) in AArch64 Linux
https://docs.kernel.org/arch/arm64/memory-tagging-extension.html
[2] glibc [PATCH v2 0/6] Memory tagging support
https://sourceware.org/pipermail/libc-alpha/2020-June/115351.html
[3] glibc.mem.tagging
https://www.gnu.org/software/libc/manual/html_node/Memory-Related-Tunables.html
[4] WIP RFC patches for -fsanitize=memtag in GCC
https://gcc.gnu.org/pipermail/gcc-patches/2024-November/668017.html
[5] Memtag ABI Extension to ELF for the ArmĀ® 64-bit Architecture (AArch64)
https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst