DF-1473 / harness.c
/* * DF-1473 harness — mpr_sas_lsi.c u16 truncation in EventDataLength*4 * * sys/dev/raid/mpr/mpr_sas_lsi.c:136 u16 sz; * :148 sz = le16toh(event->EventDataLength) * 4; * :149 fw_event->event_data = kmalloc(sz, ...); * :156 bcopy(event->EventData, fw_event->event_data, sz); * * EventDataLength is u16 (mpi2_ioc.h:563). The multiplication by 4 promotes * to int, but the assignment back to u16 truncates the high half: * - EventDataLength = 0x4000 -> sz = 0x10000 -> truncate -> 0 * kmalloc(0) returns ZERO_LENGTH_PTR (-8), non-NULL, so the NULL check * passes; later the taskqueue thread derefs fw_event->event_data * (== -8) -> page fault panic * - EventDataLength = 0x4001 -> sz = 0x10004 -> truncate -> 4 * kmalloc(4) succeeds; bcopy reads only 4 bytes from the event reply * but later parsing walks the struct fields past 4 bytes -> OOB heap * read of the M_MPR slab bucket * * The guest has no LSI SAS3 HBA, so this is a harness proof against the * genuine arithmetic from the cited source line. */ #include <stdio.h> #include <stdint.h> int main(void) { int bad = 0; struct { const char *name; uint16_t edl; } cases[] = { { "normal EventDataLength=8", 8 }, { "EventDataLength=24 (reply sz)", 24 }, { "EventDataLength=0x4000 -> sz=0", 0x4000 }, { "EventDataLength=0x4001 -> sz=4", 0x4001 }, { "EventDataLength=0x4002 -> sz=8", 0x4002 }, { "EventDataLength=0xFFFF -> sz=0xFFFC", 0xFFFF }, }; size_t n = sizeof(cases)/sizeof(cases[0]); printf("%-36s %10s %12s %12s\n", "case","EDL","buggy_sz","correct_sz"); for (size_t i=0;i<n;i++) { uint16_t edl = cases[i].edl; /* buggy line 148 */ uint16_t buggy_sz = (uint16_t)(edl * 4); /* correct computation */ uint32_t correct_sz = (uint32_t)edl * 4; printf("%-36s %10u %12u %12u\n", cases[i].name, (unsigned)edl, (unsigned)buggy_sz, correct_sz); if (buggy_sz != correct_sz) bad++; } printf("\nBuggy: %d/%zu cases produce a truncated (wrong) size.\n", bad, n); if (bad > 0) { printf("CONFIRMED: u16 sz truncation at mpr_sas_lsi.c:148 yields " "kmalloc(0) -> ZERO_LENGTH_PTR deref panic (EDL=0x4000) and " "kmalloc(4)-then-OOB-parse (EDL=0x4001). A malicious or " "compromised SAS3 HBA programming the reply DMA can choose EDL " "to control the truncated size precisely.\n"); return 0; } fprintf(stderr,"NOT CONFIRMED\n"); return 1; } |