DF-1395 / oce_overflow.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | /* * DF-1395 harness: oce_read_mac_addr firmware-controlled heap overflow. * * Replicates the EXACT vulnerable logic from: * sys/dev/netif/oce/oce_mbox.c:447-449 * mac->size_of_struct = fwcmd->params.rsp.mac.size_of_struct; // FW u16, unchecked * bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0], * mac->size_of_struct); // overflow sink * * Struct layout copied verbatim from sys/dev/netif/oce/oce_hw.h:1051-1053: * struct mac_address_format { * uint16_t size_of_struct; * uint8_t mac_addr[6]; // <-- 6-byte destination * }; * * In the kernel, `mac` is a field embedded in the device softc (POCE_SOFTC), * immediately followed by bsmbx (DMA ptr), bmbx_lock, wq[], rq[], cq[], eq[]. * A malicious/buggy OneConnect HBA firmware returning size_of_struct > 6 makes * the bcopy write past mac_addr[6] into those softc fields -> heap overflow. * * This harness cannot attach real OneConnect hardware on the QEMU guest, so it * proves the primitive deterministically: a FW-controlled size_of_struct > 6 * overflows the destination buffer. The canary field stands in for the adjacent * softc fields that get corrupted in the real kernel. * * Build: cc -O2 -o oce_overflow oce_overflow.c * Run: ./oce_overflow * Expected: "OVERFLOW CONFIRMED" with the canary overwritten by FW bytes. */ #include <stdio.h> #include <string.h> #include <stdint.h> /* ---- verbatim from sys/dev/netif/oce/oce_hw.h:1051-1053 ---- */ struct mac_address_format { uint16_t size_of_struct; uint8_t mac_addr[6]; }; /* Replicate the softc embedding: mac field followed by adjacent fields. * In the real POCE_SOFTC these are bsmbx (bus_dma_tag), locks, ring ptrs. */ struct softc_fragment { struct mac_address_format mac; /* offset 0: 2 + 6 = 8 bytes */ uint8_t adjacent_softc[64]; /* stands in for bsmbx/bmbx_lock/wq/rq/cq/eq */ }; /* Firmware response buffer (attacker/malicious-FW controlled). In the real * mailbox it is fwcmd->params.rsp.mac.mac_addr[6] followed by whatever the FW * chooses to place there. We model an oversized FW payload. */ struct fw_response { struct mac_address_format mac; /* FW sets size_of_struct here */ uint8_t fw_payload[256]; /* attacker bytes FW delivers */ }; #define CANARY 0xAA int main(void) { struct softc_fragment sc; struct fw_response fw; uint16_t fw_size; /* Setup: clean destination, mark adjacent softc fields with a canary. */ memset(&sc, 0, sizeof(sc)); memset(sc.adjacent_softc, CANARY, sizeof(sc.adjacent_softc)); /* Malicious firmware: set size_of_struct well beyond 6. * The field is a uint16_t -> max 65535. We use a representative 0x40. */ fw_size = 0x0040; /* 64 bytes */ fw.mac.size_of_struct = fw_size; /* Fill the FW source with a recognizable pattern. */ memset(fw.mac.mac_addr, 0x11, 6); memset(fw.fw_payload, 0x22, sizeof(fw.fw_payload)); printf("DF-1395 oce_read_mac_addr primitive demonstration\n"); printf("mac->mac_addr capacity: %zu bytes (sizeof mac_addr)\n", sizeof(sc.mac.mac_addr)); printf("FW-controlled size_of_struct = %u (0x%x)\n", fw_size, fw_size); /* ---- EXACT vulnerable logic (oce_mbox.c:447-449) ---- */ sc.mac.size_of_struct = fw.mac.size_of_struct; /* line 447 */ /* bcopy(src=fw mac_addr, dst=sc mac_addr, len=size_of_struct) */ memcpy(&sc.mac.mac_addr[0], /* line 448-449 */ &fw.mac.mac_addr[0], sc.mac.size_of_struct); /* Inspect the damage. */ int overflow = (fw_size > sizeof(sc.mac.mac_addr)); int canary_hit = 0; for (size_t i = 0; i < sizeof(sc.adjacent_softc) && i + sizeof(sc.mac.mac_addr) < fw_size; i++) { if (sc.adjacent_softc[i] != CANARY) { canary_hit = 1; break; } } printf("bytes written into mac_addr region: %u\n", fw_size); printf("overflow past mac_addr[6]: %s\n", overflow ? "YES -> into adjacent softc fields" : "no"); printf("adjacent softc canary corrupted: %s\n", canary_hit ? "YES" : "no"); printf("first 24 bytes after mac_addr (adjacent_softc): "); for (size_t i = 0; i < 24; i++) printf("%02x", sc.adjacent_softc[i]); printf("\n"); if (overflow && canary_hit) { printf("\nOVERFLOW CONFIRMED: FW-controlled size_of_struct (%u) bypassed the " "6-byte mac_addr and corrupted adjacent softc fields.\n", fw_size); printf("On real OneConnect HW this corrupts bsmbx/bmbx_lock/wq/rq/cq/eq -> " "heap corruption (panic or worse).\n"); return 0; } fprintf(stderr, "ERROR: overflow not observed\n"); return 1; } |