# DF-2622 — `slice = label[-1]` reads one byte below `devstr[]` on empty/'@'-only mount specs

* Cited: `sys/vfs/hammer2/hammer2_vfsops.c:1012-1020` (`hammer2_vfs_mount`)

## What this pack contains

| file | what |
|---|---|
| `mnt2622.c` | direct `mount(2)` trigger with full control of the hammer2 volume string |
| `run_2622.sh` | guest trigger battery (‘@’, ‘’, controls) |
| `run_stock.log` | stock kernel #0 run output |
| `console_excerpts.txt` | console oracle output + instrumented `devstr[-1]` byte values (0x00 vs 0xff) + fix-kernel output |
| `fix.diff` | bounds check `label > devstr` |
| build/install/env logs | shared with the other three findings (same kernels) |

## Build

Guest (root): `cc -O -o mnt2622 mnt2622.c`

## Run (as root in the guest)

```sh
./mnt2622 '@' /mnt/h2x     # devstr="@"  -> label==devstr -> devstr[-1] OOB read
./mnt2622 ''  /mnt/h2x     # devstr=""   -> label==devstr -> devstr[-1] OOB read
```

## Expected

* Console prints `hammer2_mount: device="" label="<BOOT|ROOT|DATA>"` —
  the chosen label encodes the class of the stack byte read below
  `devstr[]` ('a'→BOOT, 'd'→ROOT, anything else→DATA; ~1.6-bit oracle).
  Mount then fails ENOENT (empty device) — the OOB read has already
  happened.
* Instrumented kernel prints the actual byte: observed **0x00 on one
  call and 0xff on the very next** — live stack garbage below the array,
  varying with stack history (proof the read is out-of-bounds of any
  valid object).
* Fixed kernel: identical user-visible behavior (label=DATA default),
  `devstr[-1]` never dereferenced.

Threat: one-byte stack OOB read on the mount path; the only externally
visible consequence is the console label choice. Requires mount
privilege to trigger; console is typically privileged. Low severity as
filed — confirmed, no meaningful disclosure boundary crossed.
