DF-5364 / verdict.json
{ "finding_id": "DF-5364", "status": "untested", "verdict": "Statically certain code defect, model-demonstrated write target; kernel path not enterable in QEMU (no PCMCIA bridge). Both pccard_function allocations in pccard_parse_cis_tuple are M_NOWAIT yet unchecked: CISTPL_FUNCID at pccard_cis.c:790-791 is immediately followed by state->pf->number = state->count++ at :792, and CISTPL_CONFIG at :837-838 by the same at :839 - with offsetof(struct pccard_function, number)==0 an allocation failure becomes a write to virtual address 0 (immediate kernel panic). The CFTABLE handler in the same function checks its allocation correctly at :910-913, so the omission is an oversight, not policy. Preconditions: kmalloc failure at card insertion (small ~150B request, so kernel memory pressure is required - e.g. a system starved by the DF-5362+DF-5361 leak-loop, then re-inserted with a card whose CIS leads with FUNCID or CONFIG). Low severity panic-on-exhaustion DoS; reported for completeness/defense-in-depth. Model scenario kmallocfail injects one allocation failure at the FUNCID pf alloc and prints the exact kernel write (writes *(int*)(NULL+0) = 0 -> NULL-page write, panic).", "reproduced": false, "impact": "panic", "confidence": "certain", "exploit_chain": "memory-exhausted kernel (optionally manufactured via DF-5362+DF-5361 unbounded leak) + card insertion whose CIS contains FUNCID or CONFIG -> kmalloc(M_NOWAIT) returns NULL at pccard_cis.c:790/:837 -> *(int*)NULL = count written at :792/:839 -> kernel NULL-page write panic", "evidence": "run.log (scenario kmallocfail: RESULT: DF-5364 FUNCID kmalloc(M_NOWAIT) returned NULL; next kernel statement writes *(int*)(NULL+0) = 0 -> NULL-page write, panic); VERDICT.md (contrast with the correct :910-913 check); fix.diff", "kernel_refs": [ "sys/bus/pccard/pccard_cis.c:790", "sys/bus/pccard/pccard_cis.c:791", "sys/bus/pccard/pccard_cis.c:792", "sys/bus/pccard/pccard_cis.c:837", "sys/bus/pccard/pccard_cis.c:838", "sys/bus/pccard/pccard_cis.c:839", "sys/bus/pccard/pccard_cis.c:910" ], "poc_changes": "Wrote the full model (poc_pccard_cis2.c) with an allocation-failure injector; fixed the models CIS-image encoding after the first guest run (attribute-space tuple bytes are 2 bus-bytes apart per pccardvar.h:255-259).", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 40, "guest_dirty": 0, "build_cmd": "cc -O2 -Wall -o poc_pccard_cis2 poc_pccard_cis2.c", "run_cmd": "./poc_pccard_cis2 kmallocfail", "code_hash": "8e2bc6a40bc89ac989f57c3b43ed66138d8f5236877f64149fe2ca53df1e3e47", "notes": "No PCMCIA hardware in the QEMU guest; verified statically line-by-line plus deterministic model on the guest toolchain (DF-5355 pattern). The same unchecked-M_NOWAIT pattern in pccard_check_cis_quirks (pccard_cis_quirks.c:264-267, :272-277) is handled correctly there (continue on NULL), confirming the convention.", "recommended_fix": "NULL-check both kmalloc results (state->card->error++; break;), and add a top-of-case guard in CFTABLE_ENTRY (default_cfe==NULL || pf==NULL -> error++) so the new break-outs cannot re-expose the known DF-2319 NULLs.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored post-verification; cannot be exercised against real PCMCIA hardware here. Reviewed: the break at FUNCID exits the switch with pf left NULL, and the CONFIG break likewise - the added CFTABLE top-of-case guard turns any subsequent CFTABLE into a clean error instead of the DF-2319 NULL deref; card->error++ still causes pccard_attach_card to reject the card at pccard.c:204.", "fix_evidence": "findings/poc/DF-5364/fix.diff" } |