DF-4900 / dm_minor_alias.sh
#!/bin/sh # DF-4900 PoC: dm minor-number unit aliasing + clone-bitmap wrong-bit free # Part A (wrong-bit free / unit leak): create X, remove X, create Y -> # Y must get unit 0 again (minor 0x1E110007) if the bitmap round-trip were # correct; instead Y gets unit 1 (minor 0x1E11000F) because # dkunit(dkmakewholedisk(0)) = 0|0x200 = 512, so bit 0 is never freed. # Part B (live duplicate minors): with unit-0 device alive, create 1024 more; # the device handed unit 1024 encodes to the SAME minor as unit 0. echo "== Part A: bitmap round-trip leak ==" dmsetup create xa --notable ls -l /dev/mapper/xa | awk '{print "xa rdev:", $5, $6}' dmsetup remove xa dmsetup create ya --notable ls -l /dev/mapper/ya | awk '{print "ya rdev:", $5, $6}' echo "(expected if buggy: ya != xa minor; correct behavior: same minor)" dmsetup remove ya echo "== Part B: 1025 live devices -> duplicate minor ==" i=0 while [ $i -lt 1025 ]; do dmsetup create $(printf d%04d $i) --notable || { echo "create failed at $i"; exit 1; } i=$((i+1)) done echo "-- first (unit 0) and last (unit 1024):" ls -l /dev/mapper/d0000 /dev/mapper/d1024 | awk '{print $9, $5, $6}' echo "-- minor collision check:" m0=$(stat -f %R /dev/mapper/d0000) m1024=$(stat -f %R /dev/mapper/d1024) echo "d0000 rdev=$m0 d1024 rdev=$m1024" if [ "$m0" = "$m1024" ]; then echo "REPRODUCED: two live dm devices share the same device number" else echo "not reproduced" fi echo "-- by-minor lookup confusion (info via major:minor of d1024):" maj=$(stat -f %Hd /dev/mapper/d1024) min=$(stat -f %Ld /dev/mapper/d1024) echo "asking for minor $min (d1024's):" dmsetup info -j $maj -m $min | grep -E "Name|UUID|Major|Minor" dmsetup remove_all |