⬢ DragonFlyBSD Kernel Audit
DF-2430 / bt2430.c
← back to finding ↓ download raw
/*
 * 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;
}