DragonFlyBSD Kernel Audit
DF-1041 / harness_valid.c
← back to finding ↓ download raw
/* Sanity check: a well-formed CFTABLE_ENTRY tuple (no extension bytes)
 * must parse identically under the unpatched and patched parser logic.
 * Proves the fix doesn't break legitimate input. */
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#define PCCARD_TPCE_INDX_INTFACE  0x80
#define PCCARD_TPCE_FS_POWER_MASK 0x03
#define PCCARD_TPCE_MI_EXT        0x80

struct sim_tuple { uint8_t *img; size_t img_len; uint32_t mult, ptr, length; };

static inline uint8_t
tr1(struct sim_tuple *t, int idx) {
	size_t o = t->mult * (t->ptr + 2 + idx);
	return o < t->img_len ? t->img[o] : 0xff;
}

static int
parse(struct sim_tuple *t, int patched, int *iters)
{
	int idx = 0, i, j;
	uint32_t reg, reg2, intface, power, misc;
	*iters = 0;
	reg = tr1(t, idx); idx++; (*iters)++;
	intface = reg & PCCARD_TPCE_INDX_INTFACE;
	if (intface) { reg = tr1(t, idx); idx++; (*iters)++; }
	reg = tr1(t, idx); idx++; (*iters)++;
	power = reg & PCCARD_TPCE_FS_POWER_MASK;
	misc  = reg & 0x80;
	if (power) {
		/* only the first param-selection byte + the (zero) extension bytes */
		for (i = 0; i < (int)power; i++) {
			reg = tr1(t, idx); idx++; (*iters)++;
			for (j = 0; j < 7; j++) {
				if ((reg >> j) & 1) {
					if (patched && idx >= (int)t->length) return idx;
					do {
						reg2 = tr1(t, idx); idx++; (*iters)++;
						if (patched && idx >= (int)t->length && (reg2 & 0x80))
							return idx;
					} while (reg2 & 0x80);
				}
			}
		}
	}
	if (misc) {
		if ((int)t->length <= idx) return idx;
		reg = tr1(t, idx); idx++; (*iters)++;
		while (reg & PCCARD_TPCE_MI_EXT) {
			if (patched && idx >= (int)t->length) return idx;
			reg = tr1(t, idx); idx++; (*iters)++;
		}
	}
	return idx;
}

int main(void)
{
	/* A minimal *well-formed* CFTABLE_ENTRY tuple, attribute-memory layout
	 * (every other byte, mult=2):
	 *   byte[0]   = 0x1B (code, ignored by parse_cfe)
	 *   byte[2]   = 0x05 (length: 5 body bytes)
	 *   byte[4]   = 0x80 (INDX: interface present)
	 *   byte[6]   = 0x41 (interface byte: MWAIT + iftype=1)
	 *   byte[8]   = 0x01 (feature: power=Vcc only, no timing/io/irq/mem/misc)
	 *   byte[10]  = 0x01 (param-selection: only bit0 set, no extension)
	 *   byte[12]  = 0x2A (one power parameter byte; bit7=0 -> do-while exits)
	 */
	uint8_t img[64];
	memset(img, 0xff, sizeof(img));
	img[0]  = 0x1B;
	img[2]  = 0x05;
	img[4]  = 0x80;
	img[6]  = 0x41;
	img[8]  = 0x01;
	img[10] = 0x01;
	img[12] = 0x2A;

	struct sim_tuple t = { img, sizeof(img), 2, 0, 5 };
	int iu = 0, ip = 0;
	int u = parse(&t, 0, &iu);
	int p = parse(&t, 1, &ip);
	printf("well-formed tuple: unpatched idx=%d (%d reads), patched idx=%d (%d reads)\n",
	       u, iu, p, ip);
	if (u == p && iu == ip) {
		printf("PASS: parser reaches the same idx on legitimate input -> fix is benign.\n");
		return 0;
	} else {
		printf("FAIL: fix changed parse of legitimate input!\n");
		return 1;
	}
}