DragonFlyBSD Kernel Audit
DF-1676 / harness.c
← back to finding ↓ download raw
/* DF-1676: nvme_poll_completions unvalidated device indices.
 * res->tail.subq_id (u16) indexes sc->subqueues[NVME_MAX_QUEUES=1024].
 * res->tail.cmd_id indexes subq->reqary[nqe<=256].
 * Device-controlled values 1024..65535 read past 400KB softc.
 */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#define NVME_MAX_QUEUES 1024

static int fixed = 0;

struct subq { int nqe; char reqary[256]; int subq_head; int active; };
struct softc { char pad[400*1024]; struct subq subqueues[NVME_MAX_QUEUES]; };

static void poll_completions(struct softc *sc, uint16_t subq_id,
                             uint16_t subq_head, uint16_t cmd_id) {
    struct subq *subq;
    char *req;
    if (fixed) {
        if (subq_id >= NVME_MAX_QUEUES || !sc->subqueues[subq_id].active) {
            printf("PATCHED: rejected subq_id=%u\n", subq_id);
            return;
        }
    }
    subq = &sc->subqueues[subq_id];
    if (fixed) {
        if (subq_head >= subq->nqe) { printf("PATCHED: rejected subq_head\n"); return; }
        if (cmd_id >= subq->nqe) { printf("PATCHED: rejected cmd_id\n"); return; }
    }
    subq->subq_head = subq_head;
    req = &subq->reqary[cmd_id];
    printf("accessed subq[%u].reqary[%u] at offset %ld into softc\n",
           subq_id, cmd_id, (char*)req - (char*)sc);
}

int main(int argc, char **argv) {
    if (argc > 1 && !strcmp(argv[1], "--fixed")) fixed = 1;
    struct softc *sc = calloc(1, sizeof(*sc));
    sc->subqueues[0].nqe = 256;
    sc->subqueues[0].active = 1;

    /* attacker scenario: malicious device sends subq_id=2000, cmd_id=60000 */
    poll_completions(sc, 2000, 100, 60000);
    free(sc);
    printf("RESULT: %s\n", fixed ? "PATCHED - OOB indices rejected" : "BUGGY - OOB indices accepted");
    return 0;
}