DF-3789 / harness_frames0.c
/* * DF-3789 -- METEORSETGEO with frames=0 bypasses the bigbuf resize check * -> capture geometry (rows/cols) stored unvalidated against the * existing allocation -> OOB RISC-DMA write AND OOB read() * heap disclosure. (Distinct trigger from DF-1216: no * METEORSACTPIXFMT involved; the hole is the missing * lower-bound check on geo->frames at bktr_core.c:1642.) * * Source-level harness of the exact arithmetic of METEORSETGEO * (bktr_core.c:1657-1689), start_capture (3519-3524) and video_read * (bktr_core.c:1084-1106). */ #include <stdio.h> #define PAGE_SIZE 4096 #define PAGE_SHIFT 12 #define BROOKTREE_ALLOC_PAGES (217*4) /* bktr_core.c:157-160 */ #define BROOKTREE_ALLOC (BROOKTREE_ALLOC_PAGES * PAGE_SIZE) #define btoc(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) struct meteor_geomet { unsigned short rows, columns, frames; }; static void setgeo(int alloc_pages, struct meteor_geomet *geo, int Bpp, unsigned long ofmt_rgb24) { unsigned int temp; /* bktr_core.c:1657-1681 verbatim */ if ((temp = (geo->rows * geo->columns * geo->frames * 2))) { if (ofmt_rgb24) temp = temp * 2; if (geo->frames > 1) temp += PAGE_SIZE; temp = btoc(temp); if ((int)temp > alloc_pages) { printf(" realloc to %u pages (buffer GROWS with it)\n", temp); alloc_pages = (int)temp; /* kernel does this */ } else printf(" no realloc (temp=%u <= alloc_pages=%d)\n", temp, alloc_pages); } else { printf(" temp == 0 -> allocation block SKIPPED ENTIRELY " "(frames==0)\n"); } /* bktr_core.c:1687-1689: geometry stored regardless */ printf(" stored: rows=%u cols=%u frames=%u\n", geo->rows, geo->columns, geo->frames); /* capture footprint (RISC builders use rows/cols/Bpp only) */ { unsigned long foot = (unsigned long)geo->rows * geo->columns * Bpp; unsigned long alloc = (unsigned long)alloc_pages * PAGE_SIZE; printf(" DMA footprint = %lu B vs allocation = %lu B " "-> OOB write of %lu B past bigbuf\n", foot, alloc, foot > alloc ? foot - alloc : 0); /* video_read count = rows*cols*Bpp (bktr_core.c:1084) */ printf(" video_read uiomove count = %lu B -> OOB read of " "%lu B past bigbuf (kernel heap disclosure)\n", foot, foot > alloc ? foot - alloc : 0); } } int main(void) { struct meteor_geomet geo; int Bpp = 2; /* default METEOR_GEO_RGB16 compat format */ printf("default allocation: %d pages (%d bytes)\n\n", BROOKTREE_ALLOC_PAGES, BROOKTREE_ALLOC); printf("[*] METEORSETGEO{rows=2046, columns=1022, frames=0, RGB16}\n"); geo.rows = 2046; geo.columns = 1022; geo.frames = 0; setgeo(BROOKTREE_ALLOC_PAGES, &geo, Bpp, 0); printf("\n[*] control: frames=1 (same geometry) reallocates correctly\n"); geo.rows = 2046; geo.columns = 1022; geo.frames = 1; setgeo(BROOKTREE_ALLOC_PAGES, &geo, Bpp, 0); return 0; } |