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

Reply via email to