DF-1606 / df1606_fixed.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 112 113 114 | /* * DF-1606 - fixed-logic variant of the cmi_order[128] heap-overflow harness. * * Applies the same bound check the fix.diff introduces at acpi_hp.c:1180: if * cmi_order_size >= nitems(cmi_order), break out of the insert loop instead * of writing past the array end. With the check in place, no OOB write * occurs even with maxInstance > 128. * * Build: cc -O2 -o df1606_fixed df1606_fixed.c * Run: ./df1606_fixed ; exits 0 if NO OOB write (fix confirmed) */ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #define CMI_ORDER_N 128 #define CMI_INSTANCES 140 #define CANARY_BYTES 1024 struct acpi_hp_inst_seq_pair { uint32_t sequence; uint8_t instance; uint8_t _pad[3]; }; struct fake_softc { unsigned char header[64]; int cmi_order_size; struct acpi_hp_inst_seq_pair cmi_order[CMI_ORDER_N]; }; static int fake_wmi_seq_counter = 1; static int fake_get_cmi_block(uint32_t *sequence) { *sequence = fake_wmi_seq_counter++; return 0; } #define nitems_local(x) (sizeof((x)) / sizeof((x)[0])) int main(void) { unsigned char *block; struct fake_softc *sc; unsigned char *NEXT_SLOT_CANARY; uint32_t sequence; uint8_t instance; int maxInstance = CMI_INSTANCES; int pos, i, corrupted, first_off; block = calloc(1, sizeof(struct fake_softc) + CANARY_BYTES); if (block == NULL) { fprintf(stderr, "calloc failed\n"); return 2; } sc = (struct fake_softc *)block; NEXT_SLOT_CANARY = block + sizeof(struct fake_softc); memset(NEXT_SLOT_CANARY, 0xAA, CANARY_BYTES); /* replicate acpi_hp_hpcmi_read() lines 1171-1204 WITH the fix.diff guard */ sc->cmi_order_size = 0; for (instance = 0; instance < maxInstance; ++instance) { if (fake_get_cmi_block(&sequence)) { instance = maxInstance; } else { /* === the fix.diff guard === */ if (sc->cmi_order_size >= (int)nitems_local(sc->cmi_order)) { break; } pos = sc->cmi_order_size; for (i = 0; i < sc->cmi_order_size && i < 127; ++i) { if (sc->cmi_order[i].sequence > sequence) { pos = i; break; } } for (i = sc->cmi_order_size; i > pos; --i) { sc->cmi_order[i].sequence = sc->cmi_order[i-1].sequence; sc->cmi_order[i].instance = sc->cmi_order[i-1].instance; } sc->cmi_order[pos].sequence = sequence; sc->cmi_order[pos].instance = instance; sc->cmi_order_size++; } } corrupted = 0; first_off = -1; for (i = 0; i < CANARY_BYTES; ++i) { if (NEXT_SLOT_CANARY[i] != 0xAA) { if (first_off < 0) first_off = i; corrupted++; } } printf("maxInstance = %d\n", maxInstance); printf("cmi_order_size after = %d entries (capped at array bound %d)\n", sc->cmi_order_size, CMI_ORDER_N); printf("adjacent-slab canary corrupted bytes = %d\n", corrupted); if (corrupted == 0 && sc->cmi_order_size == CMI_ORDER_N) { printf("[OK] fix confirmed: bound check stopped the insert at %d; " "no OOB write past cmi_order[127].\n", CMI_ORDER_N); free(block); return 0; } printf("[FAIL] OOB still detected (%d bytes) or wrong cap.\n", corrupted); free(block); return 1; } |