# DF-5062 — VERDICT

**Status: REPRODUCED** (deterministic, twice, plus fix-validated). Impact:
deterministic cross-volume data corruption + wrong-object sizing. Root-gated
(vinum config path), hence Medium, not High.

## Root cause (line-accurate)

* `sys/dev/raid/vinum/vinumvar.h:83-86` — `VINUM_VOL_SHIFT=0`,
  `VINUM_VOL_WIDTH=8`: a volume device minor holds the volume number in
  **8 bits**.
* `sys/dev/raid/vinum/vinumvar.h:113-116` — `VINUMDEV(v,p,s,t)` =
  `v<<0 | p<<16 | s<<20 | t<<28`; nothing masks `v`.
* `sys/dev/raid/vinum/vinumconfig.c:759-774` — `made_vol()` does
  `make_dev(&vinum_ops, VINUMDEV(vol->volno,0,0,VINUM_VOLUME_TYPE), ...)`
  with **no range check on `vol->volno`**; `get_empty_volume()`
  (vinumconfig.c:875-899) expands `VOL[]` without limit.
* `sys/dev/raid/vinum/vinumutil.c:238-242` — `Volno(dev)` =
  `(minor(dev) & MASK(8)) >> 0` → minor 0x100 decodes as volno **0**.
* `sys/kern/kern_conf.c:70-75` — kernel `minor(cdev_t)` returns the raw
  `si_uminor` (256), so vinum really is entered with 0x100;
  `kern_conf.c:154-160` `makeudev()` only rejects it for the *stat* path
  (`ls -l` shows `255, 0xffff00ff` — the NOUDEV pattern), which is cosmetic.

## Reproduction evidence

`run.log` (stock module, fresh `vm.sh reset with-src` boot):
* 257 volumes created (`vinum l` header: `257 volumes:`).
* `ls -l /dev/vinum/vol/v256` → `crw- 255, 0xffff00ff` (v0: `32, 0x00000000`).
* `diskinfo /dev/vinum/vol/v256` → `size=0x000000400000 4.00 MB` — exactly
  v0's size, while v256 has `Plexes: 0 Size: 0 B`.
* `run.2.log` (explicit od dump): write `AAAA-v0-mark` via v0 → read via v0
  = AAAA; write `BBBB-v256-ALIAS` via **v256** → read via **v0** = BBBB.
  Writes through v256 land in v0's storage.

## Impact ceiling

Any vinum deployment with ≥257 configured volumes (volume numbers are
handed out sequentially and never reused until removal): all I/O to the
aliased node silently reads/writes a *different* volume — filesystem
corruption, swap-on-wrong-volume (DIOCGPART serves v0's geometry), and the
bogus `st_rdev` shown by stat. Attack path is the ordinary root vinum
configuration interface (`vinum create -f`), the same privilege class as
every other vinum finding in this audit (superdev open is
SYSCAP_RESTRICTEDROOT, vinum.c:457-468).

## Fix validation (done in this run)

`fix.diff` applied to the guest's `/usr/src`, vinum.ko rebuilt standalone
(`make` rc=0, fix_build.log), installed to /boot/kernel, rebooted, PoC
re-run (fix_run.log, fix_run2.log):
* kernel logs `vinum: volume v256: volume number 256 does not fit in the
  8-bit device minor; no device node created`;
* `/dev/vinum/vol/v256` absent; write attempt → ENOENT (aliasing gone);
* positive control: v0 data I/O intact (`PATCHED-OK`/AAAA readbacks).

## Not pursued

The minor-wrap also corrupts plex/sd sub-minor fields for volno ≥ 65536
(volno bits spill into bits 16+), but 65k+ volumes is not a realistic
configuration; the 8-bit wrap is the practical case.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
