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

Inverted KASSERT in bwn_phy_lp_tblinit_r2 asserts rev < 2 although it is only ever called for rev >= 2 β€” deterministic panic at PHY init on INVARIANTS kernels (upstream-inherited)

Summary

bwn_phy_lp_tblinit dispatches r2 only when mac->mac_phy.rev >= 2 but bwn_phy_lp_tblinit_r2 opens with KASSERT(mac->mac_phy.rev < 2) - inverted vs its only caller and vs the driver's own companions. On any INVARIANTS kernel the assert fails unconditionally at first LP-rev>=2 PHY init. KASSERT is a no-op on stock GENERIC, and bwn is compiled into X86_64_GENERIC. FreeBSD head carries the identical inversion. Attach/ifconfig up of an LP PHY rev>=2 device on a debug kernel -> guaranteed panic. One-token polarity fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3834 Β· 6 files
FileTypeDescriptionSize
README.md β€” 1.7 KB ↓ raw
VERDICT.md β€” 2.2 KB ↓ raw
verdict.json β€” 2.7 KB view raw
fix.diff β€” 397 B view raw
env.txt β€” 1.1 KB view raw
manifest.json β€” 637 B view raw

DF-3834 β€” Inverted KASSERT in bwn_phy_lp_tblinit_r2 (rev < 2 must be rev >= 2) β€” guaranteed panic at PHY init on INVARIANTS kernels

  • File: sys/dev/netif/bwn/bwn/if_bwn_phy_lp.c (pass 2)
  • Class: CWE-617/CWE-588 unreachable-assert inversion β†’ kernel panic at attach/init
  • Severity: Low (INVARIANTS-only: KASSERT compiles to nothing on stock GENERIC, sys/sys/systm.h:117; bwn is compiled into X86_64_GENERIC, sys/config/X86_64_GENERIC:268)
  • Hardware-gated: fires for every LP PHY rev β‰₯ 2 device (b2063 radios, e.g. BCM4313/43225-class)
  • Upstream-inherited: FreeBSD head sys/dev/bwn/if_bwn_phy_lp.c carries the same inverted assertion in its bwn_phy_lp_tblinit_r2.

Build / Run / Expected

Hardware-gated (env.txt: no Broadcom wireless on the audit guest). On an INVARIANTS kernel with an LP PHY rev β‰₯ 2 card, simply bringing the interface up panics:

kldload bwn.ko / boot with the card   # attach
ifconfig bwn0 up                      # bwn_init -> bwn_chipinit -> mac_phy.init

Expected: panic: assertion "mac->mac_phy.rev < 2" failed in bwn_phy_lp_tblinit_r2 at ...:2742.

Root cause

bwn_phy_lp_tblinit dispatches on revision β€” if_bwn_phy_lp.c:1262-1270:

    if (mac->mac_phy.rev < 2) {
            bwn_phy_lp_tblinit_r01(mac);     /* its KASSERT(rev < 2) is correct:2527 */
            ...
            return;
    }
    bwn_phy_lp_tblinit_r2(mac);              /* reached ONLY when rev >= 2 */

but bwn_phy_lp_tblinit_r2 opens with β€” if_bwn_phy_lp.c:2742:

    KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));

which contradicts its only call condition. The companion writers get it right (bwn_phy_lp_gaintbl_write_r2: KASSERT(rev >= 2), line 3661). The assertion is inverted.

VERDICT.md
↓ download raw

VERDICT β€” DF-3834

status: inconclusive (source-certain, hardware-gated) β€” reproduced: 0 β€” guest impact: none.

Proof chain

  1. bwn_phy_lp_init β†’ bwn_phy_lp_bbinit (if_bwn_phy_lp.c:440, 643-652) β†’ bwn_phy_lp_tblinit (647) β†’ for rev >= 2 calls bwn_phy_lp_tblinit_r2 (1269).
  2. bwn_phy_lp_tblinit_r2 line 2742: KASSERT(mac->mac_phy.rev < 2, ...) β€” for every caller, rev >= 2 holds, so on any kernel with INVARIANTS the assert fails unconditionally the first time an LP revβ‰₯2 PHY is initialized (device attach/ifconfig up, and again from bwn_phy_lp_bugfix:1174).
  3. KASSERT is only active with INVARIANTS (sys/sys/systm.h:94-96; no-op at 117). DragonFly's stock X86_64_GENERIC does not build with INVARIANTS, so production kernels never execute the assert β€” hence Low severity, but any debug/invariants kernel with the (GENERIC-included, sys/config/X86_64_GENERIC:268) bwn driver panics deterministically at first PHY init on this hardware class.
  4. Upstream comparison: FreeBSD head sys/dev/bwn/if_bwn_phy_lp.c bwn_phy_lp_tblinit_r2 contains the identical KASSERT(mac->mac_phy.rev < 2, ...) (verified against raw.githubusercontent.com/freebsd/freebsd-src/main, function starting at their line 2624) β€” the inversion is inherited from FreeBSD, and FreeBSD's own bwn_phy_lp_gaintbl_write_r2 (their line 3730) shows the intended polarity rev >= 2, matching DragonFly's correct usage at if_bwn_phy_lp.c:3661.

Guest

bwn is compiled into the guest kernel (kldstat -v: 62 siba_bwn/bwn) but there is no Broadcom PCI device (env.txt) β€” bwn_attach never runs, the path cannot be exercised. Guest kernel is stock GENERIC (no INVARIANTS) so even with hardware the assert would be inert there; the panic requires an INVARIANTS build.

Fix

One-token fix: < 2 β†’ >= 2 (fix.diff; git apply --check passes).

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

Baseline panic and patched non-panic both require an LP rev>=2 radio on an INVARIANTS kernel; no Broadcom hardware on the audit guest (env.txt). fix.diff is git-apply-able (verified).

fix.diff
↓ fix.diffper-fix-DF-3834

Confirmed kernel references

Detail

Exploit chain

none beyond panic: attach an LP PHY rev>=2 card to an INVARIANTS kernel -> ifconfig bwn0 up -> deterministic panic (availability only, requires the hardware + debug kernel).

Evidence (decisive lines)

README.md/VERDICT.md (dispatch at 1262-1270 vs assert at 2742; companion asserts 2527/3661; upstream comparison); env.txt; fix.diff (one-token polarity fix, git-apply --check passes)

PoC changes

No PoC β€” needs LP PHY rev>=2 hardware; also note stock GENERIC masks the assert.

Verified recommended fix

Invert the assertion to KASSERT(mac->mac_phy.rev >= 2, ...) at if_bwn_phy_lp.c:2742 (fix.diff).

Verdict

bwn_phy_lp_tblinit_r2 (sys/dev/netif/bwn/bwn/if_bwn_phy_lp.c:2555) opens with KASSERT(mac->mac_phy.rev < 2, ...) at line 2742, but its sole caller (bwn_phy_lp_tblinit, line 1269) invokes it only when rev >= 2 β€” the assertion is inverted and fails unconditionally on the first LP-PHY-rev>=2 (b2063 radio) initialization. Because KASSERT is INVARIANTS-only (sys/sys/systm.h:94-118) stock GENERIC kernels are unaffected, but any INVARIANTS kernel panics deterministically at bwn attach/ifconfig up (bwn is compiled into X86_64_GENERIC, sys/config/X86_64_GENERIC:268). The polarity is proven wrong by the driver's own companions: tblinit_r01 asserts rev < 2 (line 2527, correct for its caller at 1263) and gaintbl_write_r2 asserts rev >= 2 (line 3661). Upstream FreeBSD head carries the identical inversion (verified in its bwn_phy_lp_tblinit_r2) β€” inherited, not DF-introduced. Not exercisable on the audit guest: bwn is in the kernel but no Broadcom PCI device exists (env.txt), so the PHY init path never runs.