1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
#include <errno.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/auxv.h> #include <sys/mman.h> #include <sys/prctl.h>
#define HWCAP2_MTE (1 << 18)
#define PROT_MTE 0x20
# define PR_SET_TAGGED_ADDR_CTRL 55 # define PR_GET_TAGGED_ADDR_CTRL 56 # define PR_TAGGED_ADDR_ENABLE (1UL << 0) # define PR_MTE_TCF_SHIFT 1 # define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT) # define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT) # define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT) # define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT) # define PR_MTE_TAG_SHIFT 3 # define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
#define insert_random_tag(ptr) ({ \ uint64_t __val; \ asm("irg %0, %1" : "=r" (__val) : "r" (ptr)); \ __val; \ })
#define set_tag(tagged_addr) do { \ asm volatile("stg %0, [%0]" : : "r" (tagged_addr) : "memory"); \ } while (0)
int main() { unsigned char *a; unsigned long page_sz = sysconf(_SC_PAGESIZE); unsigned long hwcap2 = getauxval(AT_HWCAP2);
if (!(hwcap2 & HWCAP2_MTE)) return EXIT_FAILURE;
if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | (0xfffe << PR_MTE_TAG_SHIFT), 0, 0, 0)) { perror("prctl() failed"); return EXIT_FAILURE; }
a = mmap(0, page_sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (a == MAP_FAILED) { perror("mmap() failed"); return EXIT_FAILURE; }
if (mprotect(a, page_sz, PROT_READ | PROT_WRITE | PROT_MTE)) { perror("mprotect() failed"); return EXIT_FAILURE; }
a[0] = 1; a[1] = 2;
printf("a[0] = %hhu a[1] = %hhu\n", a[0], a[1]);
a = (unsigned char *)insert_random_tag(a); set_tag(a);
printf("%p\n", a);
a[0] = 3; printf("a[0] = %hhu a[1] = %hhu\n", a[0], a[1]);
printf("Expecting SIGSEGV...\n"); a[16] = 0xdd;
printf("...haven't got one\n");
return EXIT_FAILURE; }
|