pwndbg/pwndbg
View on GitHubAArch64 MTE support, broken telescope and others commands..
Open
#3,270 opened on Aug 26, 2025
bughelp wanted
Description
Blog for reading: https://www.linaro.org/blog/adding-support-for-mte-debugging-to-qemu/
Telescope: ^ should display good values for tagged addresses
vmmap:
Example program:
// zig cc -target aarch64-linux-musl -march=neoverse_n2+mte -O0 -g arm64-mte.c -o mte_demo
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/auxv.h>
#include <asm/hwcap.h>
#include <sys/prctl.h>
#include <signal.h>
#include <unistd.h>
#include <stdint.h>
#include <arm_acle.h>
#define PAGE_SIZE 4096
/*
* Insert a random logical tag into the given pointer.
* IRG instruction.
*/
#define insert_random_tag(ptr) ({ \
uint64_t __val; \
asm("irg %0, %1" : "=r" (__val) : "r" (ptr)); \
__val; \
})
/*
* Set the allocation tag on the destination address.
* STG instruction.
*/
#define set_tag(tagged_addr) do { \
asm volatile("stg %0, [%0]" : : "r" (tagged_addr) : "memory"); \
} while (0)
static void segv_handler(int sig, siginfo_t *si, void *unused) {
printf("Caught SIGSEGV at address %p (MTE violation)\n", si->si_addr);
_exit(1);
}
#define PR_MTE_TAG_SHIFT 3
int main() {
unsigned long hwcap2 = getauxval(AT_HWCAP2);
if (!(hwcap2 & HWCAP2_MTE)) {
printf("MTE not supported on this CPU\n");
return 0;
}
printf("MTE supported!\n");
prctl(PR_SET_TAGGED_ADDR_CTRL,
PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | (0xfffe << PR_MTE_TAG_SHIFT), 0, 0, 0);
// zainstaluj handler SIGSEGV
struct sigaction sa = {0};
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = segv_handler;
sigaction(SIGSEGV, &sa, NULL);
// alokacja pamięci z PROT_MTE
unsigned char *ptr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE|PROT_MTE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
/*
* Print the pointer value with the default tag (expecting 0)
*/
printf("pointer is %p\n", ptr);
/*
* Write the first 2 bytes of the memory with the default tag
*/
ptr[0] = 0x41;
ptr[1] = 0x42;
/*
* Read back to confirm the writes
*/
printf("ptr[0] = 0x%hhx ptr[1] = 0x%hhx\n", ptr[0], ptr[1]);
/*
* Generate a random tag and store it for the address (IRG instruction)
*/
ptr = (unsigned char *) insert_random_tag(ptr);
/*
* Set the key on the pointer to match the lock on the memory (STG instruction)
*/
set_tag(ptr);
/*
* Print the pointer value with the new tag
*/
printf("pointer is now %p\n", ptr);
/*
* Write the first 2 bytes of the memory again, with the new tag
*/
ptr[0] = 0x43;
ptr[1] = 0x44;
/*
* Read back to confirm the writes
*/
printf("ptr[0] = 0x%hhx ptr[1] = 0x%hhx\n", ptr[0], ptr[1]);
while(1) {}
/*
* Write to memory beyond the 16 byte granule (offsest 0x10)
* MTE should generate an exception
* If the offset is less than 0x10 no SIGSEGV will occur.
*/
printf("Expecting SIGSEGV...\n");
ptr[0x10] = 0x55;
return 0;
}