DF-1676 / harness.c
/* 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; } |