DF-1347 / trigger.c
/* DF-1347 amd_Reselect: cur_target = ffs(HostID_xor) - 1 → -1 when x==0 */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #define AMD_MAX_TARGETS 16 struct amd_softc { int tinfo_sync_period[AMD_MAX_TARGETS]; int tinfo_sync_offset[AMD_MAX_TARGETS]; void *untagged_srbs[AMD_MAX_TARGETS][8]; int disc_count[AMD_MAX_TARGETS][8]; int cur_target, cur_lun; }; static int reselect_vuln(struct amd_softc *s, uint8_t fifo_id, uint8_t HostID_Bit){ s->cur_target = fifo_id ^ HostID_Bit; s->cur_target = ffs(s->cur_target) - 1; /* -1 when 0 */ s->cur_lun = 0; int t = s->cur_target; int period = s->tinfo_sync_period[t]; /* OOB when t==-1 */ int off = s->tinfo_sync_offset[t]; int dc = s->disc_count[t][s->cur_lun]; void *a = s->untagged_srbs[t][s->cur_lun]; return period + off + dc + (a!=NULL); } static int reselect_fixed(struct amd_softc *s, uint8_t fifo_id, uint8_t HostID_Bit){ s->cur_target = fifo_id ^ HostID_Bit; /* FIX: reject x==0 or non-power-of-2 before ffs */ if (s->cur_target == 0 || (s->cur_target & (s->cur_target - 1)) != 0) { return -1; } s->cur_target = ffs(s->cur_target) - 1; s->cur_lun = 0; int t = s->cur_target; int period = s->tinfo_sync_period[t]; int off = s->tinfo_sync_offset[t]; int dc = s->disc_count[t][s->cur_lun]; void *a = s->untagged_srbs[t][s->cur_lun]; return period + off + dc + (a!=NULL); } int main(void){ struct amd_softc sc; memset(&sc, 0, sizeof(sc)); /* malicious target drives bogus reselect ID -> after XOR with HostID_Bit, result is 0 */ printf("== BEFORE-FIX (vulnerable) ==\n"); int rc = reselect_vuln(&sc, 0x01 /* HostID bit */, 0x01); printf("BUG: cur_target=%d (ffs(0)-1) -> indexed tinfo[-1], untagged_srbs[-1][0], disc_count[-1][0] OOB\n", sc.cur_target); printf("== AFTER-FIX ==\n"); memset(&sc, 0, sizeof(sc)); int rc2 = reselect_fixed(&sc, 0x01, 0x01); if (rc2 == -1) printf("FIX: invalid reselect id rejected, cur_target untouched\n"); return 0; } |