β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-3458

radiotap_offset() walks items[] past the end of the table (loop bound 31 vs array size 20) β€” latent OOB read of kernel rodata with attacker-of-driver arithmetic; plus missing table entries silently disable channel tracking for bits 14-17/20

Summary

radiotap_offset() iterates 'for (i = 0; i < IEEE80211_RADIOTAP_EXT; i++)' (i <= 30) but items[] has only 20 designated entries. Any present bit in 20..30 (AMPDU_STATUS=20, VENDOREXT=30 defined but absent from items[]) makes items[i] an OOB read of adjacent static rodata; garbage align/width then feed the offset arithmetic with size_t truncation into the int off, which could in principle drive off negative and pass the 'off + width > it_len' check, returning a bad offset that chan_change's set_channel would write through. NOT reachable through current callers: attachv only invokes radiotap_offset with item in {CHANNEL(3), XCHANNEL(18)}, both set bits so the ascending walk returns at i==item <= 18; all in-tree driver masks verified to set only bits <= 19. A driver-misuse hazard: any out-of-tree or future driver setting AMPDU_STATUS/VENDOREXT alongside CHANNEL gets an OOB rodata read at attach. Bits 14-17 set by a driver silently disable channel tracking (functional loss only). Fix: clamp the walk to nitems(items) (+ optionally add the missing entries). [VERIFIED pass2: loop bound 31 vs about-20-entry items confirmed unreachable through current callers bits le 19; nitems bound compiled]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3458 Β· 4 files
FileTypeDescriptionSize
README.md β€” 251 B ↓ raw
fix.diff β€” 487 B view raw
manifest.json β€” 389 B view raw
verdict.json β€” 1.6 KB view raw

DF-3458 evidence pack

What

radiotap_offset walks items[] past the table end (loop bound 31 vs 20 entries)

Verdict

status=not_reproduced impact=none confidence=certain

See VERDICT.md for the full narrative and fix.diff for the verified fix.

Fix verification

not_testable

fix.diff applied in the F40FIX verification kernel build (RC=0, zero -Werror errors); no runtime A/B for this item (line-certain hardening)

↓ fix.diffper-fix-DF-3458

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md with path:line citations; run.log where a live demo exists; fix.diff

PoC changes

n/a - no reachable caller passes out-of-table bits

Verified recommended fix

skip (return -1) any present-bit item beyond nitems(items)

Verdict

Line-accurate confirmation; no runtime demonstration attempted (all current callers pass item in {CHANNEL, XCHANNEL} and all in-tree driver masks set only bits <= 19, so the OOB walk is unreachable without driver misuse). radiotap_offset iterates i < IEEE80211_RADIOTAP_EXT (31) but items[] holds ~20 designated entries (ieee80211_radiotap.c:~320-360); any present bit in 20..30 makes items[i] read adjacent rodata and the garbage align/width feed the offset arithmetic (size_t truncation into int off could pass the bounds check with a negative off that callers write through). Fix bounds the walk to nitems(items); compiled in the F40FIX build.