DF-3341 / df3341.c
/* * DF-3341 harness -- TIM IE parsed without length verification * (ieee80211_input.c:586-589 scan->tim = frm) and consumed by * ieee80211_scan_sta.c:348-351 reading tim->tim_period (byte 4). * * struct ieee80211_tim_ie { tim_ie; tim_len; tim_count; tim_period; ... } * (ieee80211.h:952-956). A beacon TIM IE with declared length < 3 * yields a read of tim_period past the IE end (stale mbuf bytes drive * the scan-cache DTIM period). */ #include "guard.h" struct ieee80211_tim_ie { uint8_t tim_ie; uint8_t tim_len; uint8_t tim_count; uint8_t tim_period; } __packed; static const struct ieee80211_tim_ie *scan_tim; /* verbatim: parse_beacon TIM case */ static void parse_beacon_tim(uint8_t *frm) { scan_tim = (const struct ieee80211_tim_ie *)frm; /* no len check */ } /* verbatim: scan_sta consumer */ static int consume_tim(void) { return scan_tim->tim_period; /* byte 4 */ } static uint8_t *ie; static int v; static uint8_t *ie; static int v; int main(int argc, char **argv) { int oob = (argc > 1 && argv[1][0] == 'o'); printf("DF-3341 (TIM IE length never checked; tim_period read)\n"); ie = guard_buf(oob ? 3 : 8); ie[0] = 4; ie[1] = oob ? 1 : 5; ie[2] = 0; printf(" TIM IE declared len=%d; consumer reads tim_period (byte 4)\n", ie[1]); fflush(stdout); #ifdef FIXED /* DF-3341 fix: TIM IE must carry at least count+period */ if (ie[1] < 2) { printf("FIXED: TIM IE len %d < 2, ignored\n", ie[1]); return 0; } #endif parse_beacon_tim(ie); v = consume_tim(); printf(" ran (in bounds), tim_period=%d\n", v); return 0; } |