DF-1851 / harness.c
/* * DF-1851 source-confirmation harness (hptmv 32-bit int overflow in size sum). * * sys/dev/raid/hptmv/hptproc.c:292 (hpt_set_info, under #ifdef SUPPORT_IOCTL * which IS defined per global.h:59): * if (piop->nInBufferSize + piop->nOutBufferSize > PAGE_SIZE) return -EINVAL; * Both sizes are `DWORD`/unsigned int (hptintf.h:748,750) -> 32-bit addition * WRAPS. Example: nIn=4095, nOut=0xFFFFF001 -> sum=0x100000001 wraps to 1, * passes (1 <= PAGE_SIZE). Then kmalloc(1) and copyin(lpInBuffer, ke, 4095) * -> 4079-byte heap overflow. * * The sysctl handler (hptmv.status) IS registered on this guest (device * hptmv is in X86_64_GENERIC), but writing requires root (SYSCAP_NOSYSCTL_WR * โ maxx gets EPERM). So this is a root-only -> kernel bug: a valid hard * blocker for uid0 escalation, but the primitive is real. The harness * reproduces the 32-bit wrap arithmetic in userspace. * * Build: cc -O2 -o harness harness.c * Run: ./harness */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #define PAGE_SIZE 4096 int main(void) { /* nInBufferSize=4095, nOutBufferSize=0xFFFFF001 โ chosen so the 32-bit * sum wraps to <= PAGE_SIZE while the individual sizes are large. */ uint32_t nIn = 4095; uint32_t nOut = 0xFFFFF001u; uint32_t sum32 = nIn + nOut; /* wraps mod 2^32 โ hptproc.c:292 */ printf("DF-1851: hptproc.c:292 size check (32-bit unsigned add)\n"); printf(" nInBufferSize = 0x%08x (%u)\n", nIn, nIn); printf(" nOutBufferSize= 0x%08x (%u)\n", nOut, nOut); printf(" 32-bit sum = 0x%08x (%u)\n", sum32, sum32); printf(" sum > PAGE_SIZE (%d)? %s\n", PAGE_SIZE, sum32 > PAGE_SIZE ? "YES (rejected)" : "NO (passes โ check bypassed)"); if (sum32 <= PAGE_SIZE) { /* What the kernel then does: */ uint32_t kalloc_size = sum32; /* hptproc.c:297 kmalloc(1) */ uint32_t copyin_size = nIn; /* hptproc.c:304 copyin(4095) */ printf(" -> kmalloc(%u) returns a %u-byte slab\n", kalloc_size, kalloc_size); printf(" -> copyin(lpInBuffer, ke_area, %u) overflows it by %u bytes\n", copyin_size, copyin_size - kalloc_size); printf(" This is the FreeBSD-SA-09:11.hptmv class: integer-overflow in size sum.\n"); } return 0; } |