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

siba_pcicore_intr computes 1 << tmp with MMIO-derived tmp up to 63 (SIBA_TPS_BPFLAG=0x3f) - UB shift silently enables the wrong INTR_MASK bit on pre-rev6 PCI cores

Summary

The legacy interrupt-enable branch masks the hardware TPS register to 6 bits and shifts 1 by that value; tmp in [32,63] is undefined and on x86 silently enables bit (tmp&31) of SIBA_INTR_MASK - wrong interrupt source on the shared PCI IRQ. Correctness/availability defect inherited from upstream FreeBSD siba; no memory-safety impact. Guard-the-shift fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3927 Β· 6 files
FileTypeDescriptionSize
README.md β€” 1.6 KB ↓ raw
VERDICT.md β€” 1.0 KB ↓ raw
fix.diff β€” 430 B view raw
env.txt β€” 1.2 KB view raw
manifest.json β€” 837 B view raw
verdict.json β€” 1.5 KB view raw

DF-3927 β€” siba_pcicore_intr: 1 << tmp with hardware-derived tmp up to 63 (UB shift, wrong IRQ-mask bit on pre-rev6 PCI cores)

What

sys/dev/netif/bwn/siba/siba_core.c:2107-2138 (siba_pcicore_intr), legacy branch (ChipCommon/PCIcore sd_rev < 6 and not PCIE):

} else {
    tmp = siba_read_4_sub(sd, SIBA_TPS);
    tmp &= SIBA_TPS_BPFLAG;                        /* 0x0000003f -> tmp in [0,63] */
    siba_write_4_sub(psd, SIBA_INTR_MASK,
        siba_read_4_sub(psd, SIBA_INTR_MASK) | (1 << tmp));   /* :2131-2132 */
}

1 << tmp with tmp >= 32 is undefined behavior (C11 6.5.7). On x86 the compiler emits shl cl which masks the count to 5 bits, so a hardware TPS value of e.g. 33 enables bit 1 instead of bit 33: the wrong backplane interrupt source is enabled. That corrupts interrupt routing on the shared IRQ (missed device interrupts / interrupt storms) β€” a correctness/availability defect, not memory corruption.

  • SIBA_TPS/SIBA_TPS_BPFLAG = 0x0f18 / 0x3f (sibareg.h:258-259) β€” the value is device-controlled MMIO.
  • Upstream-inherited: identical code in FreeBSD siba (rev 299541 lineage).

Impact

Info (hardware-gated functional bug on ancient PCI-only cores; no memory safety impact). Confidence likely (UB semantics certain; observable misroute depends on TPS values the core reports).

Fix

    } else {
        tmp = siba_read_4_sub(sd, SIBA_TPS);
        tmp &= SIBA_TPS_BPFLAG;
-       siba_write_4_sub(psd, SIBA_INTR_MASK,
-           siba_read_4_sub(psd, SIBA_INTR_MASK) | (1 << tmp));
+       if (tmp < 32)
+           siba_write_4_sub(psd, SIBA_INTR_MASK,
+               siba_read_4_sub(psd, SIBA_INTR_MASK) | (1u << tmp));
    }
VERDICT.md
↓ download raw

DF-3927 VERDICT

status: not_reproduced (hardware-gated) | impact observed: none | source certainty: likely

The shift 1 << tmp at siba_core.c:2131-2132 uses a value masked to 6 bits (SIBA_TPS_BPFLAG=0x3f, sibareg.h:259) read from device MMIO (SIBA_TPS). tmp in [32,63] is undefined behavior; on x86 it silently enables bit (tmp & 31) of SIBA_INTR_MASK β€” wrong interrupt source on the shared PCI IRQ. Only reachable on cards exposing a PCI (not PCIE) core with sd_rev < 6 plus ChipCommon rev < 6 β€” pre-2004 silicon. The audit guest has no Broadcom SSB card (env.txt), so no runtime observation; filed as Info hardening / correctness. Upstream (FreeBSD siba) has the identical expression.

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.diff adds the tmp<32 guard; cannot validate without SSB hardware

fix.diff in this pack; never applied to sys/
↓ fix.diffper-fix-DF-3927

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md; sibareg.h:259 (0x3f mask) vs siba_core.c:2131 shift

PoC changes

n/a (fresh pack)

Verified recommended fix

Guard the shift: only OR (1u << tmp) when tmp < 32

Verdict

siba_pcicore_intr masks the MMIO TPS register to 6 bits (SIBA_TPS_BPFLAG=0x3f) and shifts 1 by that value (siba_core.c:2131-2132); tmp in [32,63] is UB and on x86 silently enables bit (tmp&31) of SIBA_INTR_MASK - the wrong interrupt source on the shared PCI IRQ, for pre-rev6 PCI cores only. Correctness/availability defect inherited from upstream FreeBSD siba; no memory-safety impact; not reproducible on the audit guest (no SSB hardware).