DF-3786 / harness_signcard.c
/* * DF-3786 -- BT848_SIGNATURE / signCard() unbounded sig[] bit-set loop * -> OOB read-modify-write up to ~3.8 KiB past the 260-byte * M_IOCTLOPS ioctl buffer (single-bit OR per mapped i2c dev). * * Harness: exact port of signCard() from sys/dev/video/bktr/bktr_card.c:461-476 * with an i2c stub that ACKs at the tuner read addresses (0xC1/0xC3 pattern), * exactly as any card with a tuner does. */ #include <stdio.h> #include <string.h> struct eeProm { /* ioctl_bt848.h:93-97 */ short offset; short count; unsigned char bytes[256]; }; /* i2cRead() on a real card: ACKs (returns != ABSENT) for tuner read * addresses 0xC1/0xC3 -> (2*x+1) & 0xff in {0xC1, 0xC3} */ static int i2c_stub_read(int addr) { addr &= 0xff; return (addr == 0xC1 || addr == 0xC3) ? 0x55 : -1; /* ABSENT=-1 */ } /* verbatim port of signCard() (bktr_card.c:461-476) */ static int signCard(int count, unsigned char *sig) { int x; for (x = 0; x < 16; ++x) sig[x] = 0; for (x = 0; x < count; ++x) { if (i2c_stub_read((2 * x) + 1) != -1) { sig[x / 8] |= (1 << (x % 8)); } } return 0; } int main(void) { /* 260-byte ioctl arg, canary after it */ struct { struct eeProm p; unsigned char canary[8192]; } buf; int count = 32767; /* short max, no driver-side bound */ int i, maxoff = -1; memset(&buf, 0, sizeof(buf)); buf.p.count = (short)count; signCard(count, buf.p.bytes); for (i = 0; i < 8192; i++) if (buf.canary[i] != 0) maxoff = i; printf("signCard(count=%d): OOB bit-set writes reach ioctl-buffer " "offset %d (allocation: 260 bytes)\n", count, maxoff >= 0 ? 4 + maxoff : -1); printf("highest touched index sig[%d] vs bytes[256] boundary\n", maxoff >= 0 ? maxoff : -1); printf("CONFIRMED: no bound on count; single-bit OR over ~%d bytes " "past the heap allocation\n", maxoff >= 0 ? maxoff : 0); return 0; } |