# DF-1039 — pccard_safe_quote NULL deref

## Verdict
**NOT REPRODUCED** — code-confirmed latent bug; cannot trigger on this guest (no PCMCIA bridge HW in QEMU).

## Mechanism (source-confirmed)

In `sys/bus/pccard/pccard.c`:

- `:993-1009` `pccard_safe_quote(dst, src, len)` walks `*src` in a while-loop and at `:1001` dereferences `*src` (`if (*src == '"')`) without any NULL guard on `src`.
- `:1020-1021` `pccard_child_pnpinfo_str` calls
  `pccard_safe_quote(cis0, sc->card.cis1_info[0], sizeof(cis0));`
  `pccard_safe_quote(cis1, sc->card.cis1_info[1], sizeof(cis1));`
  passing `cis1_info[0..1]` directly.
- `sys/bus/pccard/pccard_cis.c:86-89` initializes `cis1_info[0..3] = NULL`. They are assigned only when the CIS contains a `CISTPL_VERS_1` tuple with non-empty strings (`pccard_cis.c:751-754`).

So a malicious or quirky PC Card without a `VERS_1` tuple leaves `cis1_info[0]` and `[1]` NULL; the next call to `pccard_child_pnpinfo_str` dereferences `*(NULL)` → page fault → panic.

Reachability:
- automatically on card insert/remove via `devadded`/`devremoved` (`sys/kern/subr_bus.c:645/673` calls `BUS_CHILD_PNPINFO_STR`),
- or by any unprivileged user reading `sysctl hw.bus.devices.N` (`subr_bus.c:3899`).

Every other `cis1_info` consumer guards NULL: `pccard.c:974` `for (i = 0; i < 4 && sc->card.cis1_info[i] != NULL; ...)`, `pccard_cis.c:471` likewise. Only `pccard_safe_quote` does not.

## Why not reproduced on this guest

The QEMU audit guest has no PCMCIA/pccard bridge (no `pccard0`/`exca` device). The `pccard` bus is therefore never instantiated and `pccard_child_pnpinfo_str` is never invoked at runtime. There is no software-only path to reach the bug on this guest.

Per Phase-4(c)/(d): the cited path is real but unreachable on this kernel/guest because the required hardware is absent. Source-only confirmation; the bug is latent and would manifest on a real PCMCIA-equipped system or a cardbus fuzz rig.

## Fix

`fix.diff` adds a NULL guard at the top of `pccard_safe_quote`:

```c
if (src == NULL) {
    *walker = '\0';
    return;
}
```

This matches every other `cis1_info` consumer in the same file. Validated as part of a combined 5-patch kernel build that compiled cleanly and booted; pccard code path is dormant on this guest so the patched kernel behaves identically.

## Kernel references

- `sys/bus/pccard/pccard.c:993-1009` — `pccard_safe_quote` (no NULL guard on src)
- `sys/bus/pccard/pccard.c:1020-1021` — call sites pass `cis1_info[0]`/`[1]` directly
- `sys/bus/pccard/pccard_cis.c:86-89` — `cis1_info[0..3] = NULL`
- `sys/bus/pccard/pccard.c:974`, `pccard_cis.c:471` — other consumers DO guard NULL

## PoC changes

`pccard_null_deref.c` is doc-only. `fix.diff` is git-apply-able and verified to apply + compile as part of a combined patched-kernel build.
