xe_pccard_probe flag loop exits at the DINGO bit before testing it: case XE_CARD_TYPE_FLAGS_DINGO is dead code, CEM56/REM56 Dingo cards are never detected as Dingos
Summary
for(i=1; i != DINGO; i<<=1) terminates the moment i==4, so the only writer of scp->dingo is unreachable - CEM56/REM56 combo cards get the non-Dingo bring-up (skipped DCOR config, wrong modem magic writes): misconfigured/dead interface. Also masks a use-after-release in xe_activate's Dingo ioport loop that goes live once fixed. Logic mirror on guest (stock: never sets dingo; '<=' fix: exactly the two Dingo entries); if_xe.ko fix validated. Hw-gated.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4970 Β· 14 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.4 KB | β raw | |
| VERDICT.md | β | 3.1 KB | β raw | |
| dingo_flags.c | β | 5.0 KB | view raw | |
| build.sh | β | 95 B | view raw | |
| run.sh | β | 94 B | view raw | |
| build.log | β | 66 B | view raw | |
| run.log | β | 953 B | view raw | |
| run.2.log | β | 946 B | view raw | |
| run.3.log | β | 946 B | view raw | |
| env.txt | β | 942 B | view raw | |
| fix.diff | β | 367 B | view raw | |
| fix_build.log | β | 1.9 KB | view raw | |
| manifest.json | β | 778 B | view raw | |
| verdict.json | β | 3.0 KB | view raw |
DF-4970 β xe pccard: DINGO flag never set (dead switch case in probe flag loop)
sys/dev/netif/xe/if_xe_pccard.c:311 β the flag-propagation loop
for (i = 1; i != XE_CARD_TYPE_FLAGS_DINGO; i = i << 1) terminates when
i == 4 (DINGO) before evaluating it, so case XE_CARD_TYPE_FLAGS_DINGO
is dead code and scp->dingo is never set for any card β including the
CEM56/REM56 "Dingo" combo cards whose table entries
(if_xe_pccard.c:119-122) set exactly that flag.
Files
dingo_flags.cβ logic harness: verbatim tables + stock and fixed loopsbuild.shβcc -O -Wall -o dingo_flags dingo_flags.crun.shβ run harness (expect VIOLATION lines for 0x110006/0x110007)run.log,run.2.log,run.3.logβ 3 runs, identical resultfix.diffβ one-line fix (!=β<=)fix_build.logβ patchedif_xe.kobuilds on the guest with-Werrorenv.txtβ guest environment (no PCMCIA hardware)
Reproduce
sh build.sh && sh run.sh
Expected decisive lines:
0x110006 CEM56 ... stock=0,1,0 fixed=0,1,1
VIOLATION: CEM56 is a Dingo card but scp->dingo == 0 in the STOCK loop
stock loop ever sets dingo: NO (case is dead code)
RESULT: VIOLATIONS FOUND (exit=1)
Kernel-path reproduction is impossible on this guest (no PCMCIA controller / no PC card slot is emulated by this QEMU setup) β see VERDICT.md.
DF-4970 VERDICT β xe pccard DINGO dead-code: CONFIRMED at source level, kernel path not instantiable on guest
Bottom line
xe_pccard_probe() never sets scp->dingo. The loop at
sys/dev/netif/xe/if_xe_pccard.c:311-323 iterates i = 1, 2 and exits the
moment i == XE_CARD_TYPE_FLAGS_DINGO (0x4), so the case
XE_CARD_TYPE_FLAGS_DINGO: arm β the only writer of scp->dingo β is
unreachable. Every Dingo-era CEM56/REM56 combo card (table entries
XE_PROD_MULTI_ID6/ID7 at if_xe_pccard.c:119-122, flags MOHAWK|DINGO)
is therefore mis-detected as a plain Mohawk.
How it was proven
- Source trace (certain).
itakes values 1 (CE2), 2 (MOHAWK); the loop conditioni != 0x4fails at 4, so 4 is never tested. No other code path in the tree writessc->dingo(grep dingo sys/dev/netif/xe/*). - Logic harness on the DragonFly guest (
dingo_flags.c, 3 runs): for all 10 card types the stock loop leavesdingo = 0; the two CEM56 entries violate the invariant "table flags include DINGO β scp->dingo"; the one-line<=variant restores it for exactly those two entries. Build/run logs:build.log,run.log,run.2.log,run.3.log. - Fix compiles:
fix.diffapplied to the guest's/usr/srccopy buildsif_xe.kocleanly with-Werror(fix_build.log).
Why not a kernel-path reproduction
The path requires a 16-bit PCMCIA bus with a Xircom CEM56/REM56 card
inserted. The audit guest (QEMU/KVM, X86_64_GENERIC) has no PCMCIA
controller device model (env.txt: no pccard module, no /dev/card), so the
probe routine cannot be entered. Status is therefore inconclusive*
(logic-proven, hardware-gated), consistent with the family precedent
(DF-4438/DF-4613).
Impact ceiling (honest)
Functional, not memory-safety: with dingo unset,
- xe_cemfix() skips the Dingo DCOR0-4 configuration writes
(if_xe_pccard.c:201-208) β 2ndF/modem interrupt routing and EEDIO setup
never programmed for RealPort cards;
- xe_activate() never takes the Dingo aligned-ioport path
(if_xe.c:1915+) and xe_enable_intr/xe_disable_intr/LED code apply
the wrong "magic" modem bits (if_xe.c:1170,1265,1282,1916).
Result: CEM56/REM56 cards are brought up misconfigured/non-functional
(local device DoS for the inserting user; no kernel memory corruption).
Note: the Dingo branch of xe_activate contains a use-after-release read of
port_res (if_xe.c, rman_get_start after bus_release_resource) which
this bug currently keeps unreachable β fixing the flag loop without
checking that loop is not advised; both should be fixed together
(observed during this audit; filed as an observation, if_xe.c is pass-1
territory).
Fix
fix.diff: change the loop bound to i <= XE_CARD_TYPE_FLAGS_DINGO.
Validated: harness fixed-loop output + if_xe.ko builds with -Werror.
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
inconclusiveKernel-level fix validation impossible (no PCMCIA hardware). Validated at two levels instead: (1) the harness's fixed loop variant sets dingo=1 for exactly the CEM56 entries and changes nothing else; (2) fix.diff applies cleanly to the guest /usr/src copy and if_xe.ko builds with -Werror (fix_build.log). Guest sources restored after the build.
fix_build.log (patch + cc -Werror + ld -r if_xe.ko, RESTORED_CLEAN); run.log fixed column
Confirmed kernel references
Detail
Evidence (decisive lines)
run.log lines '0x110006 CEM56 ... stock=0,1,0 fixed=0,1,1' + 'VIOLATION: CEM56 is a Dingo card but scp->dingo == 0 in the STOCK loop' + 'stock loop ever sets dingo: NO (case is dead code)'; fix_build.log shows patched module linking if_xe.ko with -Werror
PoC changes
harness authored fresh (no seed); DragonFly userland queue/TAILQ conventions adapted; stock and fixed loop variants compiled from the same table
Verified recommended fix
Change the flag-propagation loop bound in xe_pccard_probe from 'i != XE_CARD_TYPE_FLAGS_DINGO' to 'i <= XE_CARD_TYPE_FLAGS_DINGO' so the DINGO case is reachable (and separately fix the port_res use-after-release in xe_activate's Dingo branch)
Verdict
CONFIRMED at source level; kernel path not instantiable on the audit guest (no PCMCIA controller device model, env.txt). xe_pccard_probe()'s flag loop (if_xe_pccard.c:311, 'for (i = 1; i != XE_CARD_TYPE_FLAGS_DINGO; i = i << 1)') exits at i==4 before testing the DINGO bit, so case XE_CARD_TYPE_FLAGS_DINGO is dead code and scp->dingo is never set for any card, including CEM56/REM56 Dingo combos (table entries if_xe_pccard.c:119-122). Guest-compiled logic harness over the verbatim table proves stock loop never sets dingo (3 runs) while the one-line '<=' fix sets it for exactly the two CEM56 entries; patched if_xe.ko builds on the guest with -Werror (fix_build.log).
No comments yet.