etc~ scripts and random things |
| git clone https://github.com/djnnvx/etc.git |
| log | files | refs | archive |
run-fuzzers.sh (7459B)
1 #!/bin/bash 2 # run-fuzzers.sh — launch linux-usb-stack syzkaller fuzzing in tmux. 3 # 4 # Three fuzzing profiles targeting different USB attack surfaces: 5 # 6 # --raw-gadget malicious USB device via syz_usb_* + raw_gadget (DEFAULT) 7 # Exercises: USB core descriptor parsing, host controller drivers, 8 # class driver binding on enumeration. 9 # 10 # --gadget-fw USB gadget framework via configfs syscalls 11 # Exercises: composite gadget, function drivers, gadget lifecycle. 12 # 13 # --usbfs userspace → kernel via /dev/bus/usb ioctls (usbfs/devio) 14 # Exercises: URB submission/cancellation, control transfers, 15 # concurrent access bugs, ioctl integer overflows. 16 # 17 # --all all three profiles simultaneously (uses 6 QEMU VMs total) 18 # 19 # Usage: 20 # bash run-fuzzers.sh [--raw-gadget|--gadget-fw|--usbfs|--all] 21 # bash run-fuzzers.sh --status # show crash counts 22 # bash run-fuzzers.sh --rerun # kill existing session and restart 23 24 set -euo pipefail 25 26 SCRIPT_DIR="$(cd "$(dirname "${0}")" && pwd)" 27 cd "${SCRIPT_DIR}" 28 29 SESSION="usb-fuzz" 30 PROFILE="raw-gadget" 31 32 log() { echo "[*] $*"; } 33 ok() { echo "[+] $*"; } 34 die() { echo "[!] $*" >&2; exit 1; } 35 36 case "${1:-}" in 37 --status) 38 # Pull Prometheus metrics from each running syz-manager instance. 39 # syzkaller exposes /metrics in Prometheus text format — machine-readable, 40 # no HTML parsing needed. Falls back to disk-based crash count if the 41 # manager isn't responding (e.g. still starting up, or not launched). 42 _status_profile() { 43 local name="${1}" port="${2}" 44 local metrics crash_count corpus_size coverage exec_total uptime 45 46 metrics="$(curl -sf --max-time 2 "http://127.0.0.1:${port}/metrics" 2>/dev/null || true)" 47 48 if [[ -n "${metrics}" ]]; then 49 _metric() { echo "${metrics}" | grep "^${1} " | awk '{print $2}' | head -1; } 50 crash_count="$(_metric syz_crash_count 2>/dev/null || echo '?')" 51 corpus_size="$(_metric syz_corpus_size 2>/dev/null || echo '?')" 52 coverage="$(_metric syz_coverage 2>/dev/null || echo '?')" 53 exec_total="$(_metric syz_exec_total 2>/dev/null || echo '?')" 54 uptime="$(_metric syz_uptime_secs 2>/dev/null || echo '?')" 55 printf " %-12s UP crashes=%-4s corpus=%-6s coverage=%-8s execs=%s\n" \ 56 "${name}" "${crash_count:-?}" "${corpus_size:-?}" "${coverage:-?}" "${exec_total:-?}" 57 else 58 # Manager not responding — count crash dirs on disk as fallback 59 local disk_crashes=0 60 [[ -d "workdir-${name}/crashes" ]] && \ 61 disk_crashes=$(find "workdir-${name}/crashes" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l) 62 printf " %-12s DOWN (crashes on disk: %d)\n" "${name}" "${disk_crashes}" 63 fi 64 } 65 66 echo "=== syzkaller USB stack fuzzer status ===" 67 echo "" 68 _status_profile "raw-gadget" 56741 69 _status_profile "gadget-fw" 56742 70 _status_profile "usbfs" 56743 71 echo "" 72 echo " Web UIs: http://127.0.0.1:56741 (raw-gadget)" 73 echo " http://127.0.0.1:56742 (gadget-fw)" 74 echo " http://127.0.0.1:56743 (usbfs)" 75 echo "" 76 echo " Tip: curl -s http://127.0.0.1:PORT/metrics | grep '^syz_'" 77 exit 0 ;; 78 --rerun) 79 tmux kill-session -t "${SESSION}" 2>/dev/null || true 80 ;; 81 --raw-gadget|"") 82 PROFILE="raw-gadget" ;; 83 --gadget-fw) 84 PROFILE="gadget-fw" ;; 85 --usbfs) 86 PROFILE="usbfs" ;; 87 --all) 88 PROFILE="all" ;; 89 *) die "Unknown option: ${1}. Use --raw-gadget, --gadget-fw, --usbfs, --all, --status, --rerun." ;; 90 esac 91 92 # ── preflight checks ───────────────────────────────────────────────────────── 93 SYZ_MANAGER="$(find "${SCRIPT_DIR}/syzkaller/bin" -name "syz-manager" -type f 2>/dev/null | head -1)" 94 [[ -n "${SYZ_MANAGER}" && -x "${SYZ_MANAGER}" ]] || die "syz-manager not found under syzkaller/bin/. Run setup.sh first." 95 [[ -f "bzImage" ]] || die "bzImage not found. Run setup.sh first." 96 [[ -f "qemu/initramfs.cpio.gz" ]] || die "qemu/initramfs.cpio.gz not found. Run setup.sh first." 97 [[ -f "qemu/id_rsa" ]] || die "qemu/id_rsa not found. Run setup.sh first." 98 command -v qemu-system-x86_64 > /dev/null || die "qemu-system-x86_64 not found." 99 100 tmux list-sessions 2>/dev/null | grep -q "^${SESSION}:" && \ 101 die "Session '${SESSION}' already running. Use --rerun to restart or --status to check." 102 103 # ── generate config from template (substitute __DIR__ with actual path) ────── 104 gen_config() { 105 local profile="${1}" 106 local tmpfile 107 tmpfile="$(mktemp /tmp/syz-${profile}-XXXXXX.cfg)" 108 sed "s|__DIR__|${SCRIPT_DIR}|g" "${SCRIPT_DIR}/syzkaller-${profile}.cfg" > "${tmpfile}" 109 echo "${tmpfile}" 110 } 111 112 # ── launch a single syz-manager instance in a named tmux window ────────────── 113 launch_profile() { 114 local profile="${1}" 115 local cfg 116 cfg="$(gen_config "${profile}")" 117 118 mkdir -p "workdir-${profile}" 119 120 local port 121 case "${profile}" in 122 raw-gadget) port=56741 ;; 123 gadget-fw) port=56742 ;; 124 usbfs) port=56743 ;; 125 esac 126 127 log "Launching syz-manager for profile '${profile}' (http://127.0.0.1:${port})..." 128 tmux new-window -t "${SESSION}" -n "${profile}" 129 tmux send-keys -t "${SESSION}:${profile}" \ 130 "${SYZ_MANAGER} -config ${cfg}" \ 131 Enter 132 } 133 134 # ── create tmux session ─────────────────────────────────────────────────────── 135 log "Creating tmux session '${SESSION}'..." 136 tmux new-session -d -s "${SESSION}" -x 220 -y 50 137 138 # The first window is created automatically; rename it to match the first profile. 139 # We'll use it for the status monitor. 140 141 if [[ "${PROFILE}" == "all" ]]; then 142 launch_profile "raw-gadget" 143 launch_profile "gadget-fw" 144 launch_profile "usbfs" 145 else 146 launch_profile "${PROFILE}" 147 fi 148 149 # ── status window ───────────────────────────────────────────────────────────── 150 tmux rename-window -t "${SESSION}:0" "status" 151 tmux send-keys -t "${SESSION}:status" \ 152 "watch -n 15 'bash ${SCRIPT_DIR}/run-fuzzers.sh --status'" \ 153 Enter 154 155 tmux select-window -t "${SESSION}:status" 156 157 ok "Fuzzing session started." 158 echo "" 159 echo " Attach: tmux attach -t ${SESSION}" 160 echo " Status: ${0} --status" 161 echo " Profile: ${PROFILE}" 162 echo "" 163 case "${PROFILE}" in 164 raw-gadget) echo " Web UI: http://127.0.0.1:56741" ;; 165 gadget-fw) echo " Web UI: http://127.0.0.1:56742" ;; 166 usbfs) echo " Web UI: http://127.0.0.1:56743" ;; 167 all) echo " Web UIs: http://127.0.0.1:56741 (raw-gadget)" 168 echo " http://127.0.0.1:56742 (gadget-fw)" 169 echo " http://127.0.0.1:56743 (usbfs)" ;; 170 esac 171 echo " Crashes: workdir-*/crashes/" 172 echo " Stop: bash cleanup.sh" 173 echo "" 174 175 tmux attach -t "${SESSION}"