# DF-3804 — `mprsas_check_eedp` error path frees a NULL path → guaranteed panic on OOM

- File: `sys/dev/raid/mpr/mpr_sas.c`
- Class: NULL-deref panic on allocation-failure path + path leak
- Severity: Low / Confidence: certain (statically provable)
- Status on guest: not_reproduced — no SAS3 HBA (see `env.txt`)

## Defect

`mprsas_check_eedp` (`mpr_sas.c:3594-3714`) allocates a local CCB at
`mpr_sas.c:3636` (zeroed: `xpt_alloc_ccb` uses `M_INTWAIT|M_ZERO`,
`sys/bus/cam/cam_xpt.c:4929-4938`, so `ccb->ccb_h.path == NULL`) and creates a
**separate** `local_path` at `mpr_sas.c:3643`.

On failure of the `M_NOWAIT` read-capacity buffer allocation
(`mpr_sas.c:3684-3692`), the error path frees the wrong path:

```c
	rcap_buf = kmalloc(sizeof(struct scsi_read_capacity_eedp), M_MPR,
	    M_NOWAIT | M_ZERO);
	if (rcap_buf == NULL) {
		...
		xpt_free_path(ccb->ccb_h.path);   /* :3689 — NULL! */
		xpt_free_ccb(&ccb->ccb_h);
		return;
	}
```

`xpt_free_path(NULL)` → `xpt_release_path(NULL)` → `CAM_DEBUG(path,...)` /
`path->device` deref (`sys/bus/cam/cam_xpt.c:4044-4067`) → **NULL-deref panic**.
(With `CAMDEBUG` enabled, `xpt_path_comp(cam_dpath, NULL)` faults first at
`cam_xpt.c:4080+`.)

Additionally `local_path` itself leaks in this path (and note the neighboring
success path correctly uses `xpt_free_path(local_path)`-style handling via the
completion callback `mprsas_read_cap_done`, `mpr_sas.c:3781`).

Trigger: `kmalloc(M_NOWAIT)` failure during EEDP probe of a newly-found
protected LUN — i.e., under real memory pressure during device discovery.
OOM-gated → Low severity, but the panic is deterministic once the allocation
fails.

## Fix

Free `local_path` (the actual allocation), not the never-assigned
`ccb->ccb_h.path`. See `fix.diff`.

## Guest verification

No SAS3 HBA → `mprsas_check_eedp` unreachable at runtime. Static proof only.
See `env.txt`.

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