# DF-4595 — `read_drive_label()` ignores the `read_drive()` error and decides on stale/uninitialized heap

* File: `sys/dev/raid/vinum/vinumio.c:336-337`
* Severity: Low · Confidence: certain (missing check) / likely (impact)

## What

```c
vhdr = (struct vinum_hdr *) Malloc(VINUMHEADERLEN);   /* NOT zeroed */
...
drive->state = drive_up;                              /* be optimistic */
error = read_drive(drive, (void *) vhdr, VINUMHEADERLEN, VINUM_LABEL_OFFSET);
if (vhdr->magic == VINUM_MAGIC) {                     /* error never tested */
```

`Malloc` is plain `kmalloc(M_DEVBUF, …)` (vinumext.h:258) — no `M_ZERO`. If
`read_drive()` fails (media error, device yanked, I/O fault), `vhdr` holds
whatever the heap had. Because the previous call in the same scandisk loop
does `Malloc(VINUMHEADERLEN)` … `Free(vhdr)` of the same size class, a
failing read very likely resurrects the **previous partition's valid header**
(same 512-byte block reused), so `vhdr->magic == VINUM_MAGIC` still holds and
the failed drive is classified `DL_OURS` with the *previous* drive's label:
`drive->label = vhdr->label` copies the stale identity, `check_drive()` then
merges the device into the configuration under a wrong name.

## Impact

* Wrong-drive acceptance on read error → the config may bind a different
  device to a drive name; subsequent I/O for that drive's subdisks goes to
  the device that failed (or nothing at all if open fails later). On a
  mirrored setup this is a data-integrity hazard, not a memory-safety one.
* If the recycled buffer contains no NUL in `label.name`-adjacent bytes, the
  `strcmp(drive->label.name, vhdr->label.name)` at line 339 walks beyond the
  512-byte allocation (OOB read; both operands are in-struct here so it
  usually terminates, but it is unbounded in principle).

## Why untested (no guest run)

Forcing a *failing* sector read at exactly `VINUM_LABEL_OFFSET` of an
otherwise valid ≥1 MiB vinum partition requires either real failing media or
emulator-level fault injection (QEMU blkdebug on the nata path); not feasible
on the standard guest snapshot within this run. The missing `if (error)` is
however directly visible in the source and trivially fixed.

## Fix

```diff
     error = read_drive(drive, (void *) vhdr, VINUMHEADERLEN, VINUM_LABEL_OFFSET);
-    if (vhdr->magic == VINUM_MAGIC) {
+    if (error == 0 && vhdr->magic == VINUM_MAGIC) {
```
(and let the error fall through to the `DL_CANT_OPEN`/`DL_NOT_OURS` handling
in `check_drive()`).
