# DF-0624 — OOB heap read in smb_t2_placedata via malicious TRANS2 response

## Reproduce

The bug is a **client-side** SMB1 parsing flaw, so the PoC is a *malicious
server* plus a victim that mounts its share.

### 1. Build
```
./build.sh        # syntax-check the Python server (stdlib only)
```
The kernel-side fix is built separately via `nativekernel` (see `fix.diff`).

### 2. Run (live)
```
env CLAIM_PCOUNT=65535 BODY_BYTES=200 ./run.sh mount
```
`run.sh` -> `run_live.sh` starts `malicious_smb_server.py` on the **host**
(listens on TCP 445 *and* 139, the DragonFly smb client default port), then
drives the **guest** victim: `kldload smb`, `mount_smbfs -N -I <host>`, `ls`.
Any file op issues a TRANS2, to which the server replies with a lying
`ParameterCount`/`DataCount`.

### Expected (bug present, unpatched #0 kernel)
With a large lie (`CLAIM_PCOUNT=65535`, `BODY_BYTES=200`) the guest **panics**
(`panic.txt`, captured from `dfbsd-qemu/boot.log`):
```
panic: overflowed mbuf 0xfffff801175c3c00
m_free -> m_freem -> md_done -> smb_t2_done -> smbfs_findclose
```
preceded by `md_get_mem(474): incomplete copy` (OOB read of the inflated chain)
and `bug: ecnt = 16705` (16705 == 0x4141, the attacker's fill bytes being
decoded as structure counts). With a small lie (`CLAIM_PCOUNT=512`) the guest
stays up and the same corruption appears in `dmesg` (the silent leak path).

### After the fix (patched kernel, see `fix.diff`)
`smb_t2_placedata()` rejects the lying response with `EBADRPC` before
mutating `m_len`; `ls`/mount fails with a benign error, **no panic, guest
stays up**. See `VERDICT.md`.

## Files
- `malicious_smb_server.py` — minimal malicious SMB1 server (NBSS + NEGOTIATE +
  SESSION_SETUP + TREE_CONNECT + lying TRANS2).
- `run_live.sh` — driver: host server + guest client, kills server on exit.
- `fix.diff` — `git apply`-able fix (`if (count > len) return EBADRPC;`).
- `panic.txt`, `server_panic.log`, `run.log` — captured evidence.
- `VERDICT.md` — full mechanism + before/after.
