DF-4429 / victim_bo.c
/* * DF-4429 PoC companion โ victim: allocates a radeon GTT GEM BO filled with a * marker pattern and parks, so a second (attacker) user can sweep the card's * vma space and find the marker in a BO it holds no handle for. * * Uses only the public radeon DRM ioctls (no libdrm): DRM_IOCTL_RADEON_GEM_CREATE * + DRM_IOCTL_RADEON_GEM_MMAP would hand us our own offset โ we deliberately * do NOT print it as a hint; the attacker must find the BO by sweeping. * * Build: cc -O2 -o victim_bo victim_bo.c */ #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> #include <drm/radeon_drm.h> /* build with -I/usr/src/sys/dev/drm/include/uapi (uapi headers not installed * into /usr/include on DFly); see build.sh */ int main(void) { const char *card = "/dev/dri/card0"; struct drm_radeon_gem_create gc = { .size = 4UL * 1024 * 1024, .alignment = 0, .initial_domain = RADEON_GEM_DOMAIN_GTT, /* user-visible TT BO */ .flags = 0, }; struct drm_radeon_gem_mmap mm = { 0 }; int fd = open(card, O_RDWR); unsigned int i; int r; if (fd < 0) { perror("open card"); return 1; } r = ioctl(fd, DRM_IOCTL_RADEON_GEM_CREATE, &gc); if (r) { perror("GEM_CREATE"); return 1; } mm.handle = gc.handle; r = ioctl(fd, DRM_IOCTL_RADEON_GEM_MMAP, &mm); if (r) { perror("GEM_MMAP"); return 1; } printf("victim: BO handle=%u size=%llu โ filling marker DF4429MARK...\n", gc.handle, (unsigned long long)gc.size); { char *p = mmap(NULL, gc.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mm.addr_ptr); if (p == MAP_FAILED) { perror("victim mmap own BO"); return 1; } for (i = 0; i + 10 < gc.size; i += 4096) memcpy(p + i, "DF4429MARK", 10); } printf("victim: parked. attacker may now run ./poc_mmap_bo --read\n"); for (;;) pause(); return 0; } |