# DF-0726 — if_cloners list / if_cloners_count unlocked race

## Summary

The `if_cloners` list (`sys/net/if_clone.c:43`) and `if_cloners_count`
(`:44`) are accessed without holding `ifnet_lock` in four functions:
`if_clone_attach` (:147,:166-167), `if_clone_detach` (:192-194),
`if_clone_list` (:207,:216,:219-221), and `if_clone_lookup` (:300).

The reader (`if_clone_list`) is reachable from the **unprivileged**
`SIOCIFGCLONERS` ioctl (`sys/net/if.c:2017-2018` — no `caps_priv_check`).
The writers (`if_clone_attach`/`if_clone_detach`) are called from module
load/unload (root-only `kldload`/`kldunload`).

A concurrent reader-vs-writer race can cause the reader to dereference a
freed/unmapped `ifc` pointer (UAF read) after module unload calls
`vm_map_remove` (`sys/kern/link_elf_obj.c:904`), panicking the kernel.

## How to reproduce

```sh
./build.sh    # cc -O2 -pthread -o reader2 reader2.c  (and reader)
./run.sh      # starts reader as maxx + kldload/kldunload loop as root
```

Expected (bug present): kernel panic (fatal trap in `if_clone_list` or
`copyout` during list traversal, reading unmapped module memory).
Expected (fixed): no panic; reader returns correct cloner list; modules
load/unload cleanly.

## Files

- `reader.c` — single-threaded SIOCIFGCLONERS hammer (unprivileged reader).
- `reader2.c` — multi-threaded + `madvise(MADV_DONTNEED)` copyout-window widener.
- `build.sh` / `run.sh` — exact build/run commands.
- `VERDICT.md` — full analysis, mechanism trace, reproduction attempts, fix validation.
- `fix.diff` — verified fix (ifnet_lock wrapping all list accesses).
- `fix_build.log` — full kernel build output (rc=0).
- `fix_run.log` — patched-kernel functional test results.
- `run.log` — unpatched-kernel race attempt results (3 attempts, 265M iters, no panic).
- `env.txt` — guest environment (uname, kern.version, cc, kernel sha256).
- `manifest.json` — artifact catalog.
