# DF-1442 — INQUIRY TRIM status writes past short inquiry buffer (heap overflow)

**File:** `sys/dev/disk/ahci/ahci_cam.c` (`ahci_xpt_scsi_disk_io`, INQUIRY case, lines 1134-1139)
**Severity:** High — kernel heap overflow at boot for any TRIM-capable AHCI SATA disk.

## What the bug is

`ahci_xpt_scsi_disk_io()` unconditionally writes the disk's TRIM status into
`rdata->inquiry_data.vendor_specific1[0]/[1]` (byte offsets **96/97** of the
inquiry buffer) whenever the disk reports DSM/TRIM support. CAM Domain
Validation (`PROBE_INQUIRY_BASIC_DV1/DV2` in `sys/bus/cam/cam_xpt.c`) allocates
only a `kmalloc(38)` inquiry buffer for AHCI disks (because AHCI sets
`additional_length=32` → `SID_ADDITIONAL_LENGTH=37` → `roundup2(,2)=38`). The
writes at byte 96/97 therefore land **58/59 bytes past the 38-byte allocation**,
overflowing into the adjacent slab object. This fires automatically at boot.

## Reachability note (why a harness, not a live in-kernel run)

The audit guest has **no AHCI SATA disk** (only `vtblk0` virtio-blk + `acd0`
DVD-ROM on the legacy `ata(4)` driver). The `ahci_xpt_scsi_disk_io` path is
only reachable via an `ahci(4)` HBA with a disk, which the guest's QEMU config
does not provide. The driver is compiled in (`device ahci`) and the module
exists, but there is no hardware to probe. The struct layout and offset
arithmetic are identical in-kernel, so `harness.c` reproduces the exact
vulnerable write using the **verbatim** kernel structs and the exact DV1
allocation math, with a canary guard to detect the out-of-bounds write.

## Build & run

```
./build.sh     # cc -Wall -Wextra -O2 -o harness harness.c
./run.sh       # ./harness  (runs UNPATCHED + PATCHED logic modes)
```

## Expected output

```
[UNPATCHED] mode=0 ... canary clobbered at 96/97: YES / YES
*** HEAP OVERFLOW CONFIRMED (mode 0) ***
[PATCHED] mode=1   ... canary clobbered at 96/97: no / no
*** NO OVERFLOW (mode 1): write correctly skipped/guarded ***
VERDICT: bug reproduced on unpatched logic, fixed on patched logic.
```

## The fix

`fix.diff` adds a size guard before the write:
`if (support_dsm && rdata_len >= offsetof(struct scsi_inquiry_data, vendor_specific1) + 2)`.
For the 38-byte DV buffer, `38 >= 98` is false → write skipped. For a full
inquiry buffer, the write proceeds as before. Apply with `patch -p1 < fix.diff`.

## Threat model

Not an unprivileged-user→root privesc. The written bytes come from the disk's
own IDENTIFY data at boot-time DV probe; an unprivileged user cannot present a
fake IDENTIFY, trigger the boot-time probe, or shape boot-time slab layout. The
attacker is a malicious AHCI/USB-SATA device. On GENERIC (INVARIANTS ON) the
adjacent-chunk corruption trips slab checks → panic/DoS at boot; on a
non-INVARIANTS kernel it is silent heap corruption.

## Files

- `harness.c` — deterministic userspace harness (verbatim kernel structs).
- `build.sh` / `run.sh` — build/run.
- `fix.diff` — git-apply-able size-guard fix.
- `VERDICT.md` — full analysis.
- `build.log`, `run.log` — harness build/run output.
- `fix_build.log`, `fix_run.log` — patched-kernel build + harness-on-patched output.
- `env.txt` — guest environment.
- `manifest.json` — artifact catalog.
