1 /* 2 * To be compiled with -march=armv8.5-a+memtag 3 * 4 * This test is adapted from a Linux test. Please see: 5 * 6 * https://www.kernel.org/doc/html/next/arch/arm64/memory-tagging-extension.html#example-of-correct-usage 7 */ 8 #include <errno.h> 9 #include <stdint.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <unistd.h> 13 #include <sys/auxv.h> 14 #include <sys/mman.h> 15 #include <sys/prctl.h> 16 #include <string.h> 17 /* 18 * From arch/arm64/include/uapi/asm/hwcap.h 19 */ 20 #define HWCAP2_MTE (1 << 18) 21 22 /* 23 * From arch/arm64/include/uapi/asm/mman.h 24 */ 25 #define PROT_MTE 0x20 26 27 /* 28 * Insert a random logical tag into the given pointer. 29 */ 30 #define insert_random_tag(ptr) ({ \ 31 uint64_t __val; \ 32 asm("irg %0, %1" : "=r" (__val) : "r" (ptr)); \ 33 __val; \ 34 }) 35 36 /* 37 * Set the allocation tag on the destination address. 38 */ 39 #define set_tag(tagged_addr) do { \ 40 asm volatile("stg %0, [%0]" : : "r" (tagged_addr) : "memory"); \ 41 } while (0) 42 43 44 int main(int argc, char *argv[]) 45 { 46 unsigned char *a; 47 unsigned long page_sz = sysconf(_SC_PAGESIZE); 48 unsigned long hwcap2 = getauxval(AT_HWCAP2); 49 50 /* check if MTE is present */ 51 if (!(hwcap2 & HWCAP2_MTE)) { 52 return EXIT_FAILURE; 53 } 54 55 /* 56 * Enable the tagged address ABI, synchronous or asynchronous MTE 57 * tag check faults (based on per-CPU preference) and allow all 58 * non-zero tags in the randomly generated set. 59 */ 60 if (prctl(PR_SET_TAGGED_ADDR_CTRL, 61 PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | PR_MTE_TCF_ASYNC | 62 (0xfffe << PR_MTE_TAG_SHIFT), 63 0, 0, 0)) { 64 perror("prctl() failed"); 65 return EXIT_FAILURE; 66 } 67 68 a = mmap(0, page_sz, PROT_READ | PROT_WRITE, 69 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 70 if (a == MAP_FAILED) { 71 perror("mmap() failed"); 72 return EXIT_FAILURE; 73 } 74 75 printf("a[] address is %p\n", a); 76 77 /* 78 * Enable MTE on the above anonymous mmap. The flag could be passed 79 * directly to mmap() and skip this step. 80 */ 81 if (mprotect(a, page_sz, PROT_READ | PROT_WRITE | PROT_MTE)) { 82 perror("mprotect() failed"); 83 return EXIT_FAILURE; 84 } 85 86 /* access with the default tag (0) */ 87 a[0] = 1; 88 a[1] = 2; 89 90 printf("a[0] = %hhu a[1] = %hhu\n", a[0], a[1]); 91 92 /* set the logical and allocation tags */ 93 a = (unsigned char *)insert_random_tag(a); 94 set_tag(a); 95 96 printf("%p\n", a); 97 98 return 0; 99 } 100