# DF-0858 — Unbounded dive depth in hpfs_hpbmap (cyclic AlSec infinite loop)

**Bug:** `hpfs_hpbmap()` at `sys/vfs/hpfs/hpfs_alsubr.c:78,110` walks the
on-disk AlNode/AlSec allocation tree via a `dive:` label and `goto dive`
with **no depth counter, no visited-set, and no cycle detection**.  A crafted
HPFS image with two AlSecs that point at each other (A→B→A) drives the loop
into an **infinite kernel CPU spin** that is unkillable (SIGKILL cannot be
delivered while in kernel mode).

**Trigger (unprivileged):** an admin mounts a crafted HPFS image
(realistic precondition); an unprivileged user then does `cat /mnt/FILE` or
even `stat /mnt/FILE` → `VOP_READ`/`VOP_GETATTR` → `hpfs_hpbmap` → infinite
dive.  After the first pass both AlSec buffers are `B_CACHE`, so `bread()`
returns immediately = tight CPU spin.

**Impact:** DoS — unkillable kernel CPU spin.  No corruption → no escalation.

## Files

| file | purpose |
|---|---|
| `craft_img.py`   | HPFS image crafter: cyclic AlSec A↔B (or control A→leaf) |
| `df858.img`      | crafted 80 KB HPFS image with cyclic A↔B (binary) |
| `df858-control.img` | control image: A→leaf AlSec (loop terminates normally) |
| `harness.c`      | deterministic dive-loop harness with depth-counter escape |
| `build.sh`       | exact `cc` command |
| `run.sh`         | exact harness invocation |
| `VERDICT.md`     | full narrative + fix validation |
| `fix.diff`       | `git apply`-able fix: dive-depth cap (HPFS_DIVE_MAX=20) |

## Build

```
./build.sh        # cc -O2 -Wall -o harness harness.c
```

## Run (deterministic harness — safe)

```
./run.sh          # ./harness
```

Expected (BUG PRESENT): harness prints
```
DF_0858_BUG_CYCLIC_DIVE_LOOPS_FOREVER=1
DF_0858_FIX_DEPTH_CAP_BREAKS_LOOP=1
DF_0858_CONTROL_TERMINATES_NORMALLY=1
DF_0858_BUG_CONFIRMED=1
```

## Run (live — destructive; will hang the guest)

```
# as root:
mdconfig/vnconfig the image, mount_hpfs -o ro /dev/vnX /mnt
# as unprivileged user:
timeout 10 cat /mnt/FILE &
# watch from a second ssh — top/systat will show one CPU pegged at 100%,
# the cat process is in pfork/wait and CANNOT be killed (kill -9 has no
# effect — it's spinning in kernel mode).  The guest becomes sluggish.
# Recover only with:  ./dfbsd-qemu/vm.sh reset with-src
```
