# DF-2318 -- VERDICT

## Verdict in one line
**REPRODUCED** (verbatim-rig level; deterministic across 3/3 runs) -- impact: panic.
`pccard_safe_quote()` dereferences `sc->card.cis1_info[0]`/`[1]` == NULL at
`sys/bus/pccard/pccard.c:1001` inside `pccard_child_pnpinfo_str()` (:1020-1021);
the kernel entry path is hardware-gated (no PCMCIA bridge in QEMU -- env.txt),
so the byte-identical production `pccard.c` code was machine-extracted from the
guest's own /usr/src and driven through the real entry `pccard_attach_card()`
with the real devadded/devnomatch/sysctl-trigger surfaces.

## What was executed (the rig, DF-2319 protocol)

* `extract2.sh` sed/awk-extracts, sha256-gated against the pristine audit tree
  (`pccard.c` = `5b610669...`), byte-identical (cross-checked two ways,
  `PCCARD_BYTE_IDENTICAL=yes` in extract2_manifest.txt):
  * `pccard.c`: DPRINTF set + `pccard_ccr_read/write`, `pccard_set_default_descr`,
    `pccard_attach_card`, `pccard_detach_card`, `pccard_function_init/_free/
    _enable/_disable`, `pccard_mfc_adjust_iobase`, **`pccard_safe_quote`**,
    **`pccard_child_pnpinfo_str`**, `pccard_read_ivar` (verbatim).
  * `kern/subr_bus.c`: `resource_list_init/free/add/find/delete` +
    `bus_child_pnpinfo_str` (verbatim; `SUBR_BUS_BYTE_IDENTICAL=yes`).
  * `pccard_cis.c` parser (verbatim; the same ranges DF-2319 validated).
  * `pccardvar.h` structs/macros + constant headers (verbatim ranges).
* `rig2_shims.h` emulates ONLY the kernel environment (device tree,
  bus_alloc_resource bridge-window model, rman, power/CARD methods, kmalloc
  ledger). `device_probe_and_attach()` mirrors production subr_bus.c
  semantics: attach success -> `devadded(dev)` -> `bus_child_pnpinfo_str()`
  (subr_bus.c:2107-2114, :633-645); probe failure -> `devnomatch(dev)` does
  the same (subr_bus.c:1984/2039 -> :673); the sysctl walk
  (`hw.bus.devices`, read by `devinfo(8)` at subr_bus.c:3863-3899, world
  readable -- verified live as user `maxx` on this guest) asks every device
  for its pnpinfo string.

## The reproduced defect chain

CIS image: `MANFID + CONFIG + CFTABLE_ENTRY(io)` -- a perfectly legal card
that simply omits CISTPL_VERS_1.

1. **The CIS gate does not help** (run.log `PRE:` line): the verbatim parser
   returns `card.error=0`, `pf_head` non-empty, and leaves
   `cis1_info[0]=cis1_info[1]=NULL` (they are only ever set by CISTPL_VERS_1,
   pccard_cis.c:735-760, initialized NULL at :86-89). `pccard_attach_card`
   proceeds (pccard.c:205-212 gates only on error/empty-pf_head) and creates
   child devices (:253-259).
2. **Any of the three pnpinfo surfaces then faults at NULL**:
   * `no_vers1_devadded` (driver attaches): SIGSEGV `si_addr=0x0`
   * `no_vers1_nomatch` (no driver): SIGSEGV `si_addr=0x0`
   * `no_vers1_sysctl` (unprivileged `devinfo -v`/sysctl walk after a silent
     probe failure): SIGSEGV `si_addr=0x0`
3. **Instruction-level pinning** (disasm_proof.txt, cc 8.3 -O2, inlined
   `pccard_safe_quote` inside `pccard_child_pnpinfo_str.isra`):

       4019a6: mov 0x110(%r11),%rcx   ; rcx = sc->card.cis1_info[0]   (NULL)
       4019c0: movzbl (%rcx),%r8d     ; :1001  if (*src == '"')        <-- FAULT

   `r11 = device_get_softc()` (PCCARD_SOFTC); the rig prints
   `offsetof(pccard_softc, card.cis1_info[0]) = 0x110` -- exact match with
   the displacement. si_addr=0x0 == src, deterministic read at NULL.
   In kernel context this is a data-access page fault on the socket event
   thread -> panic at card insertion, and re-triggerable on demand by any
   unprivileged local user (`devinfo -v`, `sysctl -a`) while the card is in.

Negative control: `vers1_pnpinfo_ok` (identical card WITH VERS_1) builds
`manufacturer=0x1234 product=0x5678 cisvendor="ACME" cisproduct="Widget"
function_type=-1` and exits clean -- the crash is exactly the NULL
cis1_info, not the pnpinfo machinery.

Determinism: run.log / run.2.log / run.3.log -- identical results 3/3.

## Why this is production behavior

The crashing text is the exact `sys/bus/pccard/pccard.c` that ships in the
guest's kernel (sha256-gated extraction), compiled by the guest toolchain;
the trigger sequence (devadded/devnomatch/sysctl-walk -> bus_child_pnpinfo_str
-> pccard_child_pnpinfo_str -> pccard_safe_quote) is the production dispatch
(subr_bus.c:645/:673/:3899 -> DEVMETHOD bus_child_pnpinfo_str, pccard.c:1340).
The only non-production element is the *card* -- a crafted CIS image in a
guard buffer instead of physical attribute memory (no PCMCIA bridge exists in
QEMU; env.txt: no /dev/pccard*, 0 pccard devices in devinfo, while
`device pccard`+`device cbb` are compiled into X86_64_GENERIC).

## Fix validation (rig A/B + booted combined-fix kernel)

* Single-fix A/B (matrix.log): guard both `pccard_safe_quote` calls on
  cis1_info[0]/[1] != NULL (empty string otherwise) -> all three
  no_vers1 scenarios exit 0 with sane `cisvendor="" cisproduct=""` strings;
  every other scenario unchanged (busypanic still panics = DF-5355's bug;
  reentry still leaks = DF-5356's bug; controls stay green).
* Combined three-fix kernel: pccard.c with DF-2318+DF-5355+DF-5356 fixes
  built `-Werror` (nativekernel rc=0), installed, booted (kernel #1); the
  rig re-extracted from the RUNNING kernel's source (--allow-patched) and
  re-driven: every scenario clean (postboot_run.log). Guest reset to
  clean-source snapshot afterwards.

## Kernel references
- sys/bus/pccard/pccard.c:993 (pccard_safe_quote signature)
- sys/bus/pccard/pccard.c:1001 (`if (*src == '"')` -- the NULL deref)
- sys/bus/pccard/pccard.c:1020-1021 (unguarded cis1_info passes)
- sys/bus/pccard/pccard.c:205-212 (error/empty gates that do not check VERS_1)
- sys/bus/pccard/pccard.c:256 (device_add_child creates the child)
- sys/bus/pccard/pccard.c:1340 (bus_child_pnpinfo_str method)
- sys/bus/pccard/pccard_cis.c:86-89 (cis1_info initialized NULL)
- sys/bus/pccard/pccard_cis.c:735-760 (only VERS_1 ever sets them)
- sys/kern/subr_bus.c:645 (devadded -> pnpinfo)
- sys/kern/subr_bus.c:673 (devnomatch -> pnpinfo)
- sys/kern/subr_bus.c:174 (DEVICE_SYSCTL_PNPINFO -> pnpinfo)
- sys/kern/subr_bus.c:3899 (sysctl_devices walk -> pnpinfo)
- sys/kern/subr_bus.c:2114 (device_doattach -> devadded on attach success)

## Exploit chain
evil PC Card without CISTPL_VERS_1 -> socket insert event ->
pccard_attach_card (pccard.c:178) -> verbatim CIS parse (no error) -> child
created + probed -> devadded OR devnomatch OR later unprivileged
`devinfo -v`/`sysctl hw.bus.devices...` -> bus_child_pnpinfo_str ->
pccard_child_pnpinfo_str -> pccard_safe_quote(NULL) -> kernel-mode read at
NULL+0 -> panic (local/physical DoS; re-triggerable at will by any local
user while the card is seated). No privilege boundary is crossed: the fault
is a fixed read at NULL, not a controllable mapping.

## Environment
Guest: DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026
x86_64, cc 8.3 [DragonFly] (env.txt). Artifacts: run.log (decisive baseline,
all 7 scenarios), run.2.log/run.3.log (determinism), disasm_proof.txt,
build.log, extract2_manifest.txt (verbatim proof), matrix.log (A/B),
postboot_run.log (running-kernel source), fixes/df2318.diff (validated).

## 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.
