# DF-2622 VERDICT

**Status: reproduced (one-byte stack OOB read confirmed live; observable impact: ~1.6-bit console oracle only). Confidence: certain.**

## Root cause (line-precise)

```c
sys/vfs/hammer2/hammer2_vfsops.c:1007-1020
	label = strchr(devstr, '@');                       /* :1007 */
	if (label && ((label + 1) - devstr) > done) { ... EINVAL }
	if (label == NULL || label[1] == 0) {
		char slice;
		if (label == NULL)
			label = devstr + strlen(devstr);   /* ""    -> label==devstr */
		else
			*label = '\0';                     /* "@"   -> label==devstr */
		slice = label[-1];                      /* :1020  OOB READ        */
```

`devstr` is the 80-byte stack array `char devstr[MNAMELEN]`
(vfsops.c:929).  Two reachable inputs make `label == devstr` at :1020:

* volume string exactly `"@"` — `strchr` finds index 0, `label[1]==0`
  (the NUL), `*label='\0'` ⇒ devstr becomes `""` and label==devstr;
* volume string `""` — `label==NULL` ⇒ `label = devstr+0`.

In both cases `label[-1]` = `devstr[-1]` reads one byte **below** the
array — stale kernel-stack data.  The byte's class is then disclosed on
the console via the kprintf at :1037 (`device="" label=…`: 'a'→BOOT,
'd'→ROOT, else→DATA).

Reachability: confirmed with a direct `mount("hammer2", mp, 0, &info)`
carrying `info.volume = "@"` / `""` (the copyin at vfsops.c:989 accepts
both; the guard at :1008 does not reject them; nothing earlier in
sys_mount rejects an empty from-spec).  Root privileges (or
`vfs.usermount=1`) required to trigger — same precondition class as every
mount-spec bug.

## Observed

1. Stock kernel #0 (`run_stock.log` + `console_excerpts.txt` [A]): both
   inputs reach :1020; console shows `device="" label="DATA"` and the
   mount then fails ENOENT via `hammer2_init_devvp("")`.
2. Instrumented kernel #1 (`console_excerpts.txt` [B]):
   * `volume=""`  → `label==devstr=1 devstr[-1]=0x00`
   * `volume="@"` → `label==devstr=1 devstr[-1]=0xff`
   The byte below devstr differs between two consecutive mount(2) calls —
   it is uninitialized stack memory, not any valid object.  Neither value
   mapped to 'a'/'d' so the label printed DATA both times; the oracle is
   real (had the stale byte been 0x61/0x64, BOOT/ROOT would print and the
   mount would search for that PFS).
3. In-bounds reference behavior captured for the same code path: boot
   root mount `devstr="vbd0s1d"` → `label[-1]='d'` → ROOT (the feature
   working as intended), and `/dev/vn0@` → `label[-1]='0'` → DATA.

## Impact (honest ceiling)

One byte of kernel stack is read out of bounds; only its 3-way class
(~1.6 bits) reaches the console, which the same (privileged) user who
triggered the mount can see.  No memory content is returned to userland,
no corruption.  Low severity as filed — correct.

## Fix

```diff
-		slice = label[-1];
+		if (label > devstr)
+			slice = label[-1];
+		else
+			slice = 0;	/* empty device: no slice letter */
```

Empty device now selects the default (DATA) without the read; the
BOOT/ROOT slice-letter convenience keeps working for real devices.

## Fix validation (kernel #2)

`'@'` and `''` mounts: same ENOENT failure, same `label="DATA"` console
line, and by construction `devstr[-1]` is never dereferenced (`label >
devstr` guard).  No behavior change for valid specs (root mount still
selects ROOT via in-bounds 'd').
