# DF-0901: smbfs_node_alloc unlocked hash-bucket traversal (UAF read)

## Bug
`smbfs_node_alloc` (`sys/vfs/smbfs/smbfs_node.c:203-213`) drops the hash bucket
lock before `vget`, then does an unlocked `LIST_FOREACH` relookup at line 209.
A concurrent `smbfs_reclaim` (`:304-319`) can `LIST_REMOVE` + `kfree` a smbnode
in the same bucket mid-traversal → UAF read (freed/poisoned memory dereference).

## Impact
- **Default GENERIC (INVARIANTS ON)**: kernel panic (local DoS)
- **Without INVARIANTS**: potential stale-pointer info leak
- **No write primitive** → no escalation path (read-only UAF)
- Requires smbfs module loaded + share mounted (both root actions)

## Reproduction
Build and load the kernel module harness:
```
cd findings/poc/DF-0901
# On the DragonFly guest:
cd /root/race_harness && make
# BUG mode (unlocked traversal) — panics within ~3s:
sysctl -w debug.race_holdlock=0
kldload ./race_harness.ko
# FIX mode (locked traversal) — survives:
sysctl -w debug.race_holdlock=1
kldload ./race_harness.ko
```

The harness replicates the exact race pattern (LIST_FOREACH without lock vs
LIST_REMOVE + kfree on the same M_SMBNODE slab) and demonstrates:
- holdlock=0: Fatal trap 12 at `traverse_thread+0x40` (page fault reading freed memory)
- holdlock=1: No panic, survives indefinitely

## Fix
Re-acquire `sm_hashlock` around the relookup traversal (see `fix.diff`).
