# DF-2215 VERDICT — dm_target_zero unconditional memset on FREEBLKS bios

## Verdict: LATENT / UNREACHABLE on this kernel (code-level bug is REAL)

## Summary

`dm_target_zero_strategy` (sys/dev/disk/dm/dm_target_zero.c:43) unconditionally
calls `memset(bp->b_data, 0, bp->b_bcount)` for every bio, including
`BUF_CMD_FREEBLKS` (discard/TRIM). For a FREEBLKS bio, `bp->b_data` is NULL
(there is no data buffer for a discard operation — only an offset and length).
This would cause a NULL-deref page fault.

However, on this kernel the FREEBLKS path through dm is **unreachable**:
`dm_ops` (device-mapper.c:73) does not set `D_CANFREE`, so the dm device never
claims TRIM support. Both paths that generate FREEBLKS bios to the dm device
are blocked:

1. **VOP_FREEBLKS** → `devfs_spec_freeblks` (devfs_vnops.c:2036): checks
   `SI_CANFREE` (propagated from `D_CANFREE`) and returns early for dm devices.
2. **ffs_blkfree TRIM path** (ffs_alloc.c:1673): only taken when
   `MNT_TRIM` is set, but `mount -o trim` FAILS for dm devices:
   `"Device:/dev/mapper/xxx does not support the TRIM command"`.

The code-level bug is REAL but LATENT. It would become reachable if a future
commit adds `D_CANFREE` to `dm_ops` or if a dm target propagates FREEBLKS
bios from a TRIM-capable backing device.

## Mechanism (why the code IS buggy)

```
dm_target_zero_strategy(dm_table_entry_t *table_en, struct buf *bp)
{
    memset(bp->b_data, 0, bp->b_bcount);   // <-- NULL deref for FREEBLKS
    bp->b_resid = 0;
    biodone(&bp->b_bio1);
    return 0;
}
```

If a `BUF_CMD_FREEBLKS` bio reached this function:
- The master buf from `getpbuf`/`getnewbuf` has `b_data == NULL`
- `nestiobuf_add` (vfs_bio.c:4581) propagates: `bp->b_data = mbp->b_data + offset = NULL + offset`
- `memset(NULL+offset, 0, size)` → page fault → kernel panic

dmstrategy (device-mapper.c:385) explicitly routes FREEBLKS through the table
strategy (it is NOT bypass), so if FREEBLKS were ever generated for a dm
device, it WOULD reach the zero target.

## Proof of unreachability (from PoC run)

```
Device:/dev/mapper/df2215dev does not support the TRIM command
```

This is because `dm_ops` (device-mapper.c:73) has flags `D_DISK | D_MPSAFE`
but NOT `D_CANFREE`.

## Exploit chain

N/A — latent bug, unreachable on this kernel. No panic, no escalation.

## Fix (defense-in-depth)

Guard the memset in `dm_target_zero_strategy` against non-READ/WRITE bios.
FREEBLKS bios should complete as no-ops (the zero target has no backing store
to discard). See `fix.diff`.

## Fix validation

- **fix_status: not_testable** — the FREEBLKS path is unreachable on this kernel
  (dm_ops lacks D_CANFREE), so there is no runtime behavior to compare.
- **Validated**: fix.diff applies cleanly, compiles without errors (`-Werror`),
  dm.ko installs and loads, dm device operations (create/reload/resume) all
  work normally. The guard does not affect normal READ/WRITE operations.
