DF-2430 / bt2430.c
/* * DF-2430 source-level harness: the exact Inquire-Model parse loop of * sys/dev/disk/buslogic/bt.c:420-425 (byte-identical semantics) run * against a bt_softc-shaped buffer whose trailing canary byte proves * the one-past-the-end NUL write. * * Production code (bt.c:418-425): * u_int8_t ascii_model[5]; (btreg.h:418 -- "Fifth byte is always 0") * char model[5]; (btreg.h:638 -- LAST field of bt_softc) * for (i = 0; i < sizeof(model_data.ascii_model); i++) { * bt->model[i] = model_data.ascii_model[i]; * if (bt->model[i] == ' ') * break; * } * bt->model[i] = '\0'; * * With a 5-byte reply containing no 0x20 (documented: 5th byte is 0x00, * not space), the loop exits with i == 5 and the terminator write lands * at bt->model[5] -- one byte past the softc. */ #include <stdio.h> #include <string.h> #include <stdint.h> struct bt_tail { /* the end of struct bt_softc */ char model[5]; uint8_t canary[8]; }; int main(void) { struct { uint8_t ascii_model[5]; } model_data; struct bt_tail t; int i; /* adapter reply: 5 bytes, no space, 5th byte 0x00 (the documented * BT-757CD case) */ model_data.ascii_model[0] = '7'; model_data.ascii_model[1] = '5'; model_data.ascii_model[2] = '7'; model_data.ascii_model[3] = 'C'; model_data.ascii_model[4] = 0x00; memset(&t, 0, sizeof(t)); memset(t.canary, 0x42, sizeof(t.canary)); /* --- production loop (verbatim semantics) --- */ for (i = 0; i < sizeof(model_data.ascii_model); i++) { t.model[i] = model_data.ascii_model[i]; if (t.model[i] == ' ') break; } t.model[i] = '\0'; /* --- end production loop --- */ printf("loop exited with i=%d (model[] has 5 bytes)\n", i); printf("canary bytes after softc: %02x %02x %02x %02x %02x %02x %02x %02x\n", t.canary[0], t.canary[1], t.canary[2], t.canary[3], t.canary[4], t.canary[5], t.canary[6], t.canary[7]); printf("verdict: %s\n", t.canary[0] == 0x42 ? "canary intact (not reproduced)" : "OOB NUL WRITE at bt->model[5], one byte past the softc " "(canary 0x42 overwritten with 0x00)"); return t.canary[0] == 0x42; } |