DF-0615 / race.sh
#!/bin/sh # DF-0615 race coordinator. Run as ROOT on the guest. # Launches N readers as maxx (unprivileged) + 1 mutator as root, # lets them race for DURATION seconds, then collects anomalies. # # Usage: ./race.sh [duration] [weird] # weird=1 -> sysctl -w debug.use_weird_array=1 (poison freed chunks -> panic) set -e DURATION="${1:-18}" WEIRD="${2:-0}" DIR="$(cd "$(dirname "$0")" && pwd)" cd "$DIR" # rebuild to be safe cc -O2 -o reader reader.c cc -O2 -o mutator mutator.c # clean any prior state pkill -9 reader 2>/dev/null || true pkill -9 mutator 2>/dev/null || true sleep 0.3 rm -f r*.err r*.out m.err if [ "$WEIRD" = "1" ]; then echo "[race] enabling debug.use_weird_array=1 (freed chunks -> odd ptrs -> panic)" sysctl -w debug.use_weird_array=1 else sysctl -w debug.use_weird_array=0 2>/dev/null || true fi echo "[race] launching 6 readers as maxx (unprivileged)" for n in 1 2 3 4 5 6; do su maxx -c "cd '$DIR' && ./reader >r$n.out 2>r$n.err" & done sleep 1 echo "[race] launching mutator as root for ${DURATION}s" ./mutator "$DURATION" >m.out 2>m.err & MUT_PID=$! # Let them race. If weird=1, the kernel may panic here. wait $MUT_PID 2>/dev/null || true echo "[race] mutator finished" # give readers a moment to capture final state, then stop them sleep 1 pkill -9 reader 2>/dev/null || true sleep 0.3 sysctl -w debug.use_weird_array=0 2>/dev/null || true echo "=== mutator output (tail) ===" tail -3 m.err 2>/dev/null echo "=== anomaly counts per reader ===" TOT=0 for n in 1 2 3 4 5 6; do a=$(grep -c "UAF#" r$n.err 2>/dev/null || true) [ -z "$a" ] && a=0 m=$(grep "iters" r$n.err 2>/dev/null | tail -1) echo "r$n: anomaly_lines=$a | $m" TOT=$((TOT + a + 0)) done echo "TOTAL anomaly lines across readers: $TOT" echo "=== sample anomalies ===" grep -h "UAF#" r*.err 2>/dev/null | head -16 echo "=== sample leaked bytes ===" grep -h -A5 "leaked freed-chunk bytes" r*.err 2>/dev/null | head -60 echo "[race] done" |