DF-4351 / df4351.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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | /* * DF-4351 model proof - advansys.c (narrow AdvanSys CAM layer) * ------------------------------------------------------------ * Two unconditional panic() sites are gated only by bytes the adapter * firmware wrote into LRAM (copied unmasked by adv_copy_lram_doneq, * advlib.c:802-844): * * 1) advansys.c:1092-1094 * if ((scsiq.q_status != QS_DONE) * && (scsiq.q_status & QS_ABORTED) == 0) * panic("adv_qdone: completed scsiq with unknown status"); * QS_DISC1 (0x02) and QS_DISC2 (0x04) are legitimate queue-state * bits defined by the driver's own ABI (advlib.h:562-569); a * completion status byte of e.g. QS_DONE|QS_DISC1 (0x82) - or any * corrupt LRAM value without the QS_ABORTED bit - is an instant, * unauthenticated kernel panic. * * 2) advansys.c:1227-1237 (adv_done default arm) * case QHSTA_D_LRAM_CMP_ERROR: * case QHSTA_M_MICRO_CODE_ERROR_HALT: * default: * panic("%s: Unhandled Host status error %x", ...); * codes the driver ITSELF enumerates (0x81 LRAM compare error, * 0xA1 micro-code error halt) fall into the panic arm, plus every * value outside the switch. * * Same defect family as DF-4042 (amd.c) and DF-4308 (adwcam.c). * * This model replays the two predicates over a table of device-supplied * bytes and classifies the kernel outcome. */ #include <stdio.h> #define QS_FREE 0x00 #define QS_READY 0x01 #define QS_DISC1 0x02 #define QS_DISC2 0x04 #define QS_BUSY 0x08 #define QS_ABORTED 0x40 #define QS_DONE 0x80 /* host status codes from advlib.h:640-667 */ static const struct { int v; const char *n; } host_stats[] = { {0x00, "QHSTA_NO_ERROR"}, {0x11, "QHSTA_M_SEL_TIMEOUT"}, {0x12, "QHSTA_M_DATA_OVER_RUN"}, {0x13, "QHSTA_M_UNEXPECTED_BUS_FREE"}, {0x14, "QHSTA_M_BAD_BUS_PHASE_SEQ"}, {0x21, "QHSTA_D_QDONE_SG_LIST_CORRUPTED"}, /* -> panic arm */ {0x22, "QHSTA_D_ASC_DVC_ERROR_CODE_SET"}, /* -> panic arm */ {0x23, "QHSTA_D_HOST_ABORT_FAILED"}, /* -> panic arm */ {0x24, "QHSTA_D_EXE_SCSI_Q_FAILED"}, /* -> panic arm */ {0x26, "QHSTA_D_ASPI_NO_BUF_POOL"}, /* -> panic arm */ {0x41, "QHSTA_M_WTM_TIMEOUT"}, {0x42, "QHSTA_M_BAD_CMPL_STATUS_IN"}, {0x43, "QHSTA_M_NO_AUTO_REQ_SENSE"}, {0x44, "QHSTA_M_AUTO_REQ_SENSE_FAIL"}, {0x45, "QHSTA_M_TARGET_STATUS_BUSY"}, {0x46, "QHSTA_M_BAD_TAG_CODE"}, /* -> panic arm */ {0x47, "QHSTA_M_BAD_QUEUE_FULL_OR_BUSY"}, {0x48, "QHSTA_M_HUNG_REQ_SCSI_BUS_RESET"}, {0x81, "QHSTA_D_LRAM_CMP_ERROR"}, /* -> panic arm (enumerated!) */ {0xA1, "QHSTA_M_MICRO_CODE_ERROR_HALT"}, /* -> panic arm (enumerated!) */ {0xEE, "<undefined firmware code>"}, /* -> panic arm */ }; static const char *site1(uint8_t q_status) /* :1092-1094 */ { if ((q_status != QS_DONE) && (q_status & QS_ABORTED) == 0) return "PANIC (adv_qdone: completed scsiq with unknown status)"; return "ok"; } static const char *site2(int hs) /* :1227-1237 */ { switch (hs) { case 0x45: case 0x47: case 0x43: case 0x00: case 0x11: case 0x12: case 0x13: case 0x14: case 0x25: /* QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT */ case 0x41: case 0x42: case 0x44: case 0x48: return "ok (translated to CAM status)"; default: /* incl. 0x21,0x22,0x23,0x24, 0x26,0x46,0x81,0xA1 which the switch itself routes here */ return "PANIC (Unhandled Host status error)"; } } int main(void) { int panics = 0, i; const uint8_t qv[] = { QS_DONE, /* clean */ QS_DONE | QS_ABORTED, /* aborted completion */ QS_DONE | QS_DISC1, /* legitimate reconnect state bit */ QS_DONE | QS_DISC2, /* legitimate reconnect state bit */ QS_READY, QS_BUSY, /* mid-flight states in a done slot */ 0x00, 0xFF, 0x55 /* corrupt LRAM */ }; printf("DF-4351 model: device-fed status bytes -> panic() predicates\n"); printf("site 1: advansys.c:1092-1094 (q_status from LRAM, unmasked)\n"); printf("site 2: advansys.c:1235-1237 (host_stat from LRAM)\n\n"); printf("q_status byte | outcome at site 1\n"); printf("-------------+------------------------------------\n"); for (i = 0; i < (int)(sizeof(qv)/sizeof(qv[0])); i++) { const char *r = site1(qv[i]); if (r[0] == 'P') panics++; printf(" 0x%02X | %s%s\n", qv[i], r, (qv[i] == (QS_DONE|QS_DISC1) || qv[i] == (QS_DONE|QS_DISC2)) ? " <-- legitimate ABI bits" : ""); } printf("\nhost_stat | outcome at site 2\n"); printf("------------+------------------------------------\n"); for (i = 0; i < (int)(sizeof(host_stats)/sizeof(host_stats[0])); i++) { const char *r = site2(host_stats[i].v); if (r[0] == 'P') panics++; printf(" 0x%02X %-38s | %s\n", host_stats[i].v, host_stats[i].n, r); } printf("\n%d/%zu tabulated device-fed values lead to kernel panic\n", panics, sizeof(qv)/sizeof(qv[0]) + sizeof(host_stats)/sizeof(host_stats[0])); printf("PANIC-ON-DEVICE-STATUS CONFIRMED (model; predicates are " "verbatim advansys.c:1092-1094 / :1235-1237)\n"); return 0; } |