How to enable MTE in ArmStudio

Prerequisites:

  1. Download and install Arm Development Studio for either Linux or Windows. Obtain a 30-day evaluation license so that the project can be built successfully.
  2. Download and install Armv8-A Base RevC AEM FVP (Fixed Virtual Platform) that supports Memory Tagging Extension for Linux (No windows version online, need to be compiled by ourselves).

Procedure

  1. Create a new C project, select: File > New > Project.

  1. Expand C/C++ menu, and select C project, then click Next.
  2. Give the project a name, select project type as Executable > Empty Project, then select Arm Compiler 6 Toolchains.
  3. Add asm and src directory, create main.c file under src directory. The asm directory is organized as follows.

The FVP is a bare metal so startup.S is the startup code used to setup cache, MMU, stak and enable hardware floating point, etc. Without the startup code, even the simplest printf function cannot be executed. The startup code setups environment, then jumps to C library init code __main to execute the real function. We need to specify the entry point as start64 to run startup code at first.

  1. Right-click the project and select Properties to configure the project for further build.

    1. In the Tool Settings tab, select All Tools Settings > Target to specify the Target CPU. Here I select Cortex-A76 AArch64 (The target CPU may be not 100% consistent to the real FVP, but it should be OK.)

    1. Select Arm C Compiler 6 > Target, enable tool specific settings. We need to add +memtag feature in -mcpu option to provide hardware support for memory tagging, for more detailed information, please refer to armclang_ref.

    1. Select Arm C Compiler 6 > Miscellaneous, add flag -fsanitize=memtag so that the compiler will use memory tagging instructions (IRG, ADDG, SUBG…) during code generation to protect the memory allocations on the stack. For more detailed information, please refer to armclang_ref.

    1. Select Arm Linker 6 > Image Layout, specify the entry point as start64, then browse the scatter file.

    1. Scatter file set up the RO base address (run the code from memory 0x80000000), etc.

    1. Select Arm Linker 6 > Miscellaneous, add flag –library_security=v8.5a. This flag lets the armlink link the code with the library that compiled with memory tagging extension to provide full memory tagging stack protection. For more detailed information, please refer to armclang_ref.

    v8.5 not only provides memory tagging protection of the stack used by the library code, but also branch protection using Branch Target Identification (BTI) and Pointer Authentication Code (PAC). To enable heap protection with memory tagging (malloc, realloc, free..), we need to add code __asm(".global __use_memtag_heap\n\t") in C file.

  2. Build the project, the Debug directory will be generated. When the project has built, in the Project Explorer view, under Debug, locate the HelloWorld.axf file. The .axf file contains the object code and debug symbols that enable Arm Debugger to perform source-level debugging.

  3. Configure a debugging session to launch the FVP and connect to it.

  • Create a use_model_semihostting.ds script to disable semihosting by Arm Debugger.

  • Select File > New > Model Connection, give the connection a name and associate debug connection with an existing project.

  • The FVP Armv8-A Base RevC AEM is not involved by default so we need to add it. Select the model from file system, the path is where you install Armv8-A Base RevC AEM.

  • Once added, we need to edit the debug configuration. In the Connection tab, select Bare Metal Debug/ARMAEMv8-A_MPx4 SMP Cluster 0.

Add the model parameters as follows to enable MTE support.

1
2
3
4
5
# cluster0.has_arm_v8-5=1 implements the Armv8.5 extension.
# cluster0.memory_tagging_support_level=2 specifies the memory tagging extension support level, 2 means supported at EL0 only.
# bp.dram_metadata.is_enabled=1 lets the memory system to support storing MTE tags.
# bp.secure_memory=false disables the TZC-400 TrustZone memory controller included in the Base_A53x1 FVP. By default, the memory controller refuses all accesses to DRAM memory.
\-C cluster0.has_arm_v8-5=1 -C cluster0.memory_tagging_support_level=2 -C bp.dram_metadata.is_enabled=1 -C bp.secure_memory=false

  • In the Files tab, select .axf file under Debug directory from workspace.

  • In the Debuger tab, select Debug from entry point start64, enable run target initialization debugger script and select .ds script from workspace.

  1. Click Debug to load the application on the target, and load the debug information into the debugger. The application stops at the entry point start64.

  1. In the disassembly view, we search main to get the assembly instructions of main. The presence of IRG, ADDG shows the code is generated using memory tagging instructions. We set a breakpoint at ADDG instruction, let the program stop at this breakpoint.

Let the program continue to execute and finally we can see “Hello world!” from target console.

Use-after-free

Reference:

  1. Armv8.5-A Memory Tagging Extension White Paper https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/Arm_Memory_Tagging_Extension_Whitepaper.pdf

  2. Arm Architecture Registers Manual for Armv8-A Architecture Profile. http://harperchen.qiniudn.com/SysReg_xml_v86A-2020-06.pdf

  3. Arm A64 Instruction Set Architecture Manual for Armv8-A Architecture Profile. http://harperchen.qiniudn.com/ISA_A64_xml_v86A-2020-06_OPT.pdf