# DF-4803 — `parityops()`/`parityrebuild()` compute the transfer size with an overflowing `stripesize << DEV_BSHIFT`: one `vinum checkparity`/`rebuildparity` ioctl on a ≥2 GiB-stripe RAID-5 plex panics the kernel

* File: `sys/dev/raid/vinum/vinumrevive.c:274-275` (`parityops`),
  `:382` (`parityrebuild` `mysize`), `:386/:393` (`Malloc` of the
  wrapped value)
* Severity: Low (root-gated deterministic kernel panic from a legal
  config string; same class/file as DF-1886's div0 but a distinct
  sink — signed integer overflow into a kernel allocation)
* Bucket: base:raid / dos
* Status: **reproduced** (panic on the first ioctl)

## Root cause

```c
size = imin(DEFAULT_REVIVE_BLOCKSIZE,		    /* one block at a time */
    plex->stripesize << DEV_BSHIFT);                    /* vinumrevive.c:274 */
```

`plex->stripesize` is an `int` in **sectors**. The config parser
(`plex org raid5 3g`) accepts any size, so a stripesize ≥ 2 GiB
(≥ 2^22 sectors) makes `stripesize << 9` overflow `int`: 3 GiB
(6291456 sectors) wraps to `0xC0000000` (negative). `imin` picks the
negative value; `parityrebuild()` then computes

```c
mysize = u64min(size, (plex->stripesize * (stripe + 1) - pstripe) << DEV_BSHIFT);
...
bpp[sdno]->b_data = Malloc(mysize);			    /* vinumrevive.c:393 */
```

where the wrapped value sign-extends to ~1.8e19 as `size_t`; `Malloc`
is `kmalloc(M_WAITOK)` (`vinumext.h:258`), which cannot fail, and the
gigantic request panics in the allocator.

## Reproduction (guest, stock kernel)

`run_vbd1.sh`: legal config `plex org raid5 3g` (3×2 MB subdisks on
md/vbd partitions), all objects forced up, then ONE
`vinum checkparity`:

```
Sep 24 ... vinum: Correcting length of rv.p0: was 0, is 8192
panic: kmem_slab_alloc(): kernel_map ran out of space!
_kmalloc() at _kmalloc+0x5be
parityrebuild() at parityrebuild+0x162
parityops() at parityops+0x82
vinumioctl() at vinumioctl+0x63b
```

(`panic.log` — first ioctl, deterministic.) The 16k-stripe control
(DF-4714 pack) behaves normally.

## Fix

Compute the stripe cap in 64-bit and clamp before the `int` demotion
(same shape in `parityrebuild`):

```diff
-    size = imin(DEFAULT_REVIVE_BLOCKSIZE,
-	plex->stripesize << DEV_BSHIFT);
+    {
+	vinum_off_t s64 = (vinum_off_t)plex->stripesize << DEV_BSHIFT;
+	size = (int)u64min((u_int64_t)s64, DEFAULT_REVIVE_BLOCKSIZE);
+    }
```

## Files

* `run.sh` — md-partition variant of the probe
* `run_vbd1.sh` — the exact executed trigger (vbd1 partitions)
* `panic.log` — full serial-console panic
* `env.txt`
