# DF-5363 -- VERDICT

## Verdict in one line
**REPRODUCED** (verbatim-rig level; deterministic) -- impact: dos.
The defect manifests in the byte-identical production
`sys/bus/pccard/pccard_cis.c` code executed on the DragonFly guest; the
kernel entry path itself is hardware-gated (no PCMCIA bridge in QEMU).

REPRODUCED at the verbatim-rig level on the DragonFly guest; kernel entry hardware-gated (no PCMCIA bridge). The CISTPL_CHECKSUM handler validates addr and addr+length against PCCARD_CIS_SIZE in TUPLE-INDEX units (pccard_cis.c:247-249) but then reads bus_space_read_1(memt, memh, addr + tuple.mult * i) (pccard_cis.c:255-259) -- in attribute memory (mult=2, the primary-chain default at :145) the maximum byte offset is addr + 2*(length-1). On the verbatim parser, a card supplying offset=4, length=4091 passes the unmagnified check (4+4091=4095<4096) and produces EXACTLY the claimed 2045 out-of-mapping reads with maximum offset 8184 = 2.00x the 4096-byte mapping allocated at :62/:130-131 (counted by the rig's instrumented bus_space_read_1 against the guard buffer). Read bytes are only summed and compared -- no disclosure; realistic ceiling is the DF-2320-documented bridge behaviour (CardBus master abort -> panic; ISA adjacent-mapping reads / bus hang). checksum_ok proves sane checksums are unaffected by the fix. Fix validated: single-fix rig A/B (magnified bound -> 'too distant' skip, 0 OOB) and the combined-five-fix kernel built -Werror, booted, rig re-driven from the running kernel's patched source: 0 OOB, checksum_ok still accepted.

## Method -- the verbatim rig (why this is production code, not a model)

The guest has no PCMCIA/CardBus bridge (env.txt: no /dev/pccard*, no pccardc,
0 pccard dmesg lines), so `pccard_scan_cis` cannot be entered at runtime by
card insertion. Instead of hand-replicating the parser, the rig **machine-
extracts the production parser byte-identical from the guest's own kernel
source** and executes it:

* `extract.sh` sed-extracts, from `/usr/src/sys/bus/pccard/pccard_cis.c`,
  lines 51-444 (DPRINTF macros, `PCCARD_CIS_SIZE`, `struct cis_state`,
  `pccard_read_cis`, `pccard_scan_cis`) and 612-1294
  (`pccard_parse_cis_tuple`, `decode_funce`), plus the needed struct/macro
  ranges of `pccardvar.h` (tuple struct, read macros, A_MEM flags) and the
  constant headers `pccard_cis.h`/`pccardreg.h` whole.
* The extraction is **sha256-gated**: all four pccard files plus
  `sys/sys/queue.h` must match the audited pristine tree
  (`acdd2484...` for pccard_cis.c); `extract_manifest.txt` in this pack is
  the guest-generated record. The userland `<sys/queue.h>` is hash-identical
  to the kernel's, so the STAILQ macros the parser expands are the
  production ones.
* `rig_shims.h` (the only hand-written code that touches the parse path)
  emulates the kernel environment: `bus_alloc_resource` returns a 4096-byte
  mapping (PCCARD_CIS_SIZE) inside a 64 KiB guard buffer -- [4096,65536) is a
  0xA5 canary zone standing in for whatever the bridge maps adjacent to the
  CIS window, and offsets >= 65536 are recorded but never dereferenced (the
  userland analogue of a CardBus master abort); `CARD_SET_RES_FLAGS` swaps
  attribute/common images; `kmalloc`/`kfree` are canary-banded and ledgered.
  Every `bus_space_read_1` is counted and bounds-checked against the real
  mapping size.
* `rig_main.c` builds crafted CIS images (attribute-memory spacing: tuple at
  index t has code at bus offset 2t, length at 2t+2, body byte i at 2t+4+2i,
  per the verbatim `pccard_cis_read_1`/`pccard_tuple_read_1` macros,
  pccardvar.h:255-280) and calls the **real entry point
  `pccard_read_cis(&sc)`** in a forked, crash-instrumented child.

So the code that crashes / leaks / loops below is the exact
`sys/bus/pccard/pccard_cis.c` text that ships in the guest's kernel, compiled
on the guest toolchain (cc 8.3).

## A/B discipline

`run_matrix.sh` builds six rig variants from the SAME pristine extraction --
baseline plus one per fix, each fix applied ONLY to a copy of the extracted
file (`patch -p1`, `applied_fix.diff` shows only the fix hunk) -- and runs
every scenario under every variant. Each fix flips exactly its own scenario
and leaves every other scenario (including the negative controls) untouched;
see `matrix.log` and the summary table in this file.


## matrix.log summary (baseline + each single-fix variant)

| scenario      | baseline           | f2319      | f2320      | f5361      | f5362          | f5363      |
|---------------|--------------------|------------|------------|------------|----------------|------------|
| nullderef_a   | SEGV si_addr=0x0   | ret clean  | SEGV       | SEGV       | SEGV           | SEGV       |
| nullderef_b   | SEGV si_addr=0x30  | ret clean  | SEGV       | SEGV       | SEGV           | SEGV       |
| wildlink_long | OOB=1 @16777216    | same       | OOB=0      | same       | same           | same       |
| wildlink_mfc  | OOB=2 max 67108864 | same       | OOB=0      | same       | same           | same       |
| mfcleak       | LIVE cfe=2 leaked  | same       | same       | LIVE cfe=0 | same           | same       |
| livelock      | NONTERM (periodic) | same       | same       | same       | ret (hop cap)  | same       |
| leakloop      | NONTERM, cfe grows | same       | same       | same       | ret, cfe=64    | same       |
| checksum      | OOB=2045 max 8184  | same       | same       | same       | same           | OOB=0      |
| checksum_ok   | OOB=0              | same       | same       | same       | same           | same       |
| benign (valid)| clean, LIVE cfe=3  | clean      | clean      | LIVE cfe=2 | clean          | clean      |


## Kernel-level fix validation (combined five-fix kernel)

1. All five fix.diffs `patch -p1`-applied to the guest's `/usr/src`
   (kernel_apply.log; patched pccard_cis.c sha256 `67334ef6...`).
2. `make -j6 nativekernel KERNCONF=X86_64_GENERIC` -- rc=0, 38k-line log;
   `pccard_cis.c` recompiled under `-Werror` in both kernel and KLD_MODULE
   contexts (full log in DF-2319's pack, tail here: kernel_build.tail.log).
3. `make installkernel` -- rc=0; rebooted into
   `6.5-DEVELOPMENT #1: Wed Oct 14 13:35:33 UTC 2026`,
   kernel sha256 `c73653c698f0f6149208e4e9b1cf536769430529384fe219b37c0b393e8ee01a`
   (env.txt).
4. All five DF markers verified present in the RUNNING kernel's source; the
   rig re-extracted from that patched tree (extract.sh reports
   `SOURCE_STATE=PATCHED`, postboot_extract_manifest.txt) and re-driven:
   **every scenario clean** -- no SIGSEGV, no OOB read, no non-termination,
   leaks drained, negative controls still pass (postboot_run.log).
5. Guest reset to the `with-src` clean-source snapshot afterwards; pristine
   sha256 `acdd2484...` re-verified (guest left up and clean).

Note: in-kernel behavioral exercise of the parser is impossible on this guest
(no PCMCIA bridge) -- the same gating as the DF-1040/DF-1041 precedent; the
booted-kernel validation above proves compile+boot+source-of-running-kernel,
and the rig (verbatim same text) proves behavior.


## Unit-confusion evidence

Crafted CHECKSUM (offset=4, length=4091, mult=2): passes :247-249 because
4+4091 = 4095 < 4096 (tuple-index units), then :255-259 reads at
`addr + tuple.mult * i` for i<4091 -> byte offsets 4..8184.
Rig counters: **OOB = 2045 reads, first = 4096, max = 8184** -- the exact
numbers claimed in the finding (2.00x the mapping). `checksum_ok`
(offset 0, length 100) does 110 in-window reads -- the negative control both
baseline and fixed.

## Fix (fix.diff -- validated)
Magnify the length term in the too-distant check: 'addr + tuple.mult * length >= PCCARD_CIS_SIZE' instead of 'addr + length >= PCCARD_CIS_SIZE'.

* rig A/B: fixed_run.log (this pack) + matrix.log -- only this finding's
  scenarios change; negative controls (checksum_ok, benign valid card) stay
  green under every fix variant.
* kernel: see "Kernel-level fix validation" above.

## Kernel references
- `sys/bus/pccard/pccard_cis.c:62`
- `sys/bus/pccard/pccard_cis.c:130`
- `sys/bus/pccard/pccard_cis.c:131`
- `sys/bus/pccard/pccard_cis.c:145`
- `sys/bus/pccard/pccard_cis.c:221`
- `sys/bus/pccard/pccard_cis.c:237`
- `sys/bus/pccard/pccard_cis.c:247`
- `sys/bus/pccard/pccard_cis.c:248`
- `sys/bus/pccard/pccard_cis.c:255`
- `sys/bus/pccard/pccard_cis.c:259`

## Exploit chain
evil card -> pccard_attach_card -> pccard_read_cis -> pccard_scan_cis -> CISTPL_CHECKSUM with offset/length chosen to pass the unmagnified :247-249 check -> 2045 bus_space_read_1 calls at byte offsets 4096..8184 on a 4096-byte mapping -> bridge-dependent master-abort panic / adjacent-mapping reads / bus hang (DoS)

## Environment
Guest: 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 (audits) / booted fixed kernel #1 for fix validation
(env.txt). cc 8.3 [DragonFly]. Artifacts: extract_manifest.txt (verbatim
proof), run.log (baseline decisive), fixed_run.log (fix A/B),
baseline_run.log (full pristine run), matrix.log (6x11 A/B),
postboot_run.log (running-kernel source), env.txt, build.log.

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