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

ath_tdma_settimers computes DBA/SWBA alerts with 32-bit (nexttbtt<<3) while nexttbtt is the full TSF-derived TU value β€” inconsistent timer wrap corrupts beacon timers after ~6.2 days of continuous TDMA operation (the in-file unaudited wrap TODO)

Summary

nextslottu is the unclamped 32-bit TU of the received beacon TSF; DBA/SWBA = (nexttbtt<<3)-prep truncate at 2^29 TU (~6.2 days) while the HAL consumes bt_nexttbtt with a different wrap point (<<10, 2^22 TU) - the three coupled timers wrap inconsistently; the file's own TODO comments say negative/large jumps 'cause the timers to stop and generally cause instability'. Admin-configured TDMA, >6.2-day sessions; not attacker-triggerable on demand. 64-bit-compute-then-truncate-once fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4723 Β· 4 files
FileTypeDescriptionSize
README.md β€” 652 B ↓ raw
VERDICT.md β€” 3.7 KB ↓ raw
fix.diff β€” 1.1 KB view raw
verdict.json β€” 2.0 KB view raw

DF-4723 β€” PoC evidence pack

Finding: 32-bit (nexttbtt<<3) truncation in ath_tdma_settimers DBA/SWA math vs full-range TU nexttbtt β€” beacon-timer corruption after ~6.2 days of continuous TSF (the in-file "wrap family" TODO, never audited upstream).

Contents

  • VERDICT.md β€” wrap-point analysis (driver <<3 at 2^29 TU vs HAL TU_TO_USEC at 2^22 TU), path:line.
  • verdict.json β€” machine verdict (status: untested; needs 6+ days radio).
  • fix.diff β€” 64-bit math, single truncation point.

Reproduce / Expected

Requires ~6.2 days of continuous TDMA operation on Atheros hardware β€” not reproducible on the QEMU guest.

VERDICT.md
↓ download raw

DF-4723 β€” ath_tdma_settimers: 32-bit (nexttbtt<<3) truncation in the DBA/SWBA math vs full-range TU nexttbtt β€” beacon-timer corruption after ~6.2 days of TSF (acknowledged-unaudited wrap family)

File: sys/dev/netif/ath/ath/if_ath_tdma.c Β· Severity: Low Β· Bucket: base:dev (DoS) Β· Confidence: certain

Root cause (path:line)

The file itself documents the un-audited wrap family (comment at if_ath_tdma.c:345-353: "please audit it to ensure that when the TU values programmed into the timers wrap at (2^31)-1 TSF, all the various terms wrap consistently"). They do not:

  • nextslottu is the full 32-bit TU value derived from the received beacon's TSF: TSF_TO_TU(nextslot>>32, nextslot) = TSF >> 10 truncated to u32 (if_ath_tdma.c:444) β€” a monotonically growing value that reaches 2^29 TU after ~6.2 days of continuous TSF runtime (2^29 TU Γ— 1024 Β΅s). It is passed unclamped to ath_tdma_settimers(sc, nextslottu, ...) (if_ath_tdma.c:576).
  • Inside ath_tdma_settimers() (if_ath_tdma.c:137-189):
    bt.bt_nexttbtt = nexttbtt;                                    /* 143 */
    bt.bt_nextdba = (nexttbtt<<3) - sc->sc_tdmadbaprep;           /* 144 */
    bt.bt_nextswba = (nexttbtt<<3) - sc->sc_tdmaswbaprep;         /* 145 */
    bt.bt_nextatim = nexttbtt+1;                                  /* 146 */

nexttbtt << 3 is 32-bit unsigned arithmetic: it silently truncates for nexttbtt β‰₯ 2^29, i.e. exactly when the TSF-derived TU value crosses 2^29 β€” wrapping the DBA/SWBA alert targets to small values (i.e. the past).

  • Meanwhile the HAL truncates at a different point: ar5416_beacon.c:48-50 writes AR_NEXT_TBTT = TU_TO_USEC(bt_nexttbtt) (= <<10, wraps at 2^22 TU) but AR_NEXT_DBA/SWBA = ONE_EIGHTH_TU_TO_USEC(bt_nextdba/nextswba) (built from the already-wrapped <<3 values). The three timers therefore wrap inconsistently: nexttbtt stays coherent up to 2^22 TU while dba/swba corrupt from 2^29 TU.

Per the in-file comment (if_ath_tdma.c:563-569): "Negative jumps larger than the beacon interval seem to cause the timers to stop and generally cause instability" β€” i.e. after ~6.2 days of continuous TDMA operation the station's beacon alert timers are programmed with wrapped garbage: SWBA/DBA stop firing or fire continuously (interrupt storm), the TDMA link collapses until reconfiguration (ath_tdma_config resets TSF via HAL_BEACON_RESET_TSF, if_ath_tdma.c:303-304, which is why long-lived TDMA sessions are required to hit it).

Related sub-issue in the same function family: (nexttbtt<<3) - prep underflows (no saturation) whenever nexttbtt is small but prep is large, and bt.bt_nextatim = nexttbtt+1 wraps at 2^32-1.

Impact

Correctness/availability (DoS of the TDMA link after ~6.2 days continuous operation; possible SWBA interrupt storm). Requires admin-configured TDMA on long-lived ATH infrastructure. Certain at the arithmetic level; the file's own TODO confirms it was never audited upstream.

Verification

Requires ~6.2 days of radio TSF runtime β€” not reproducible in the QEMU guest; arithmetic verified by inspection (shift widths, types, HAL consumers).

Compute the DBA/SWBA targets in u_int64_t and truncate once, so all three timers share one wrap point (and clamp the TSF-derived nextslottu to the hardware timer domain before programming). See fix.diff.

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

Fix not kernel-validated: requires ~6.2 days of radio TSF runtime on Atheros hardware in TDMA mode.

fix.diff authored against read-only sys/.
↓ fix.diffper-fix-DF-4723

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md (shift/type/width analysis + HAL consumer semantics), fix.diff

PoC changes

n/a

Verified recommended fix

Do the TU->1/8TU DBA/SWBA math in 64-bit and truncate once so all timers share a single wrap point

Verdict

ath_tdma_settimers (if_ath_tdma.c:137-189) builds bt_nextdba/bt_nextswba with 32-bit (nexttbtt<<3) - prep (:144-145) while nexttbtt is the full TSF-derived 32-bit TU value from the received beacon (nextslottu = TSF_TO_TU(nextslot>>32, nextslot), :444, passed at :576); the shift truncates at 2^29 TU (~6.2 days of continuous TSF) whereas the HAL wraps nexttbtt itself at 2^22 TU (ar5416_beacon.c:48-50: TU_TO_USEC vs ONE_EIGHTH_TU_TO_USEC) β€” the three beacon timers wrap inconsistently, and per the in-file comment (:563-569, TODO at :345-353) that leads to stopped timers / instability / SWBA storms: TDMA link DoS on >6-day-old sessions. Arithmetic is certain; runtime repro needs ~6.2 days of radio TSF (impossible in QEMU, no ath NIC).