# DF-0103 — ktrace() mutates target p_tracenode without p_token (double-free)

| | |
|---|---|
| Verdict | **REPRODUCED** |
| Impact | kernel panic / local DoS (tracenode double-free race) |
| File | `sys/kern/kern_ktrace.c:386,369` (ktrops `:514-518`, ktrdestroy `:481`) |

## Build
```
cc -O2 -o race race.c
```

## Run (unprivileged)
```
./race
```

## Expected (bug present)
Within ~seconds the kernel panics and the guest drops to DDB:
```
panic: assertion "tracenode->kn_refs > 0" failed in ktrdestroy at kern_ktrace.c:481
ktrdestroy() -> ktrops() -> sys_ktrace()
```
ssh session dies; panic captured in `dfbsd-qemu/boot.log`.

## Expected (fixed)
The process runs to completion and prints `RACE_DONE: no panic`.

## Mechanism (short)
`sys_ktrace` holds only the caller's `curp->p_token`, not the target's. Two
separate caller processes (same uid) both call `ktrace(KTROP_SET, target)` and
each snapshots `oldnode = p->p_tracenode` then `ktrdestroy(&oldnode)` — the
second destroy sees `kn_refs == 0` → `KKASSERT` → panic.

See `VERDICT.md` for the full analysis and `fix.diff` for the patch.
