DF-4590 / trigger.sh
#!/bin/sh # DF-4590 trigger โ tws(4) driver-callout use-after-free on detach/unload # # VULNERABILITY: sys/dev/raid/tws/tws.c:346-410 (tws_detach) and the # attach-failure unwinds (tws.c:309-341) never cancel the driver's # callouts before freeing the memory they reference: # # sc->reset_cb_handle scheduled tws_cam.c:1217,1232 (hz/10 poll loop) # sc->reinit_handle scheduled tws_cam.c:1238,1256 (5 s poll loop, # self-reschedules while !tws_ctlr_ready()) # req->thandle scheduled tws_cam.c:847,893 (60 s timeouts on # AEN-fetch / get-set-param requests) # # tws_detach() tears down the interrupt, kfrees sc->reqs (tws.c:398), # kfree()s the queues, and lockuninit()s โ with no callout_stop/cancel # anywhere โ so a pending callout fires into freed memory (UAF panic or # heap corruption in softirq context). # # TRIGGER RECIPE (requires a 3ware 9700-series controller, PCI 13C1:1010): # 1. Build tws as a module: cd sys/dev/raid/tws && make && kldload ./tws.ko # (X86_64_GENERIC compiles tws into the kernel; module config is needed # so the code can be unloaded โ see VERDICT.md preconditions.) # 2. Induce controller distress so a reset/reinit poll is pending, e.g.: # - cause I/O errors / pull the controller into tws_reset (watch # dmesg for "Resetting controller" โ this schedules # reset_cb_handle at hz/10 and, when the soft reset does not # complete, reinit_handle every 5 s indefinitely), or # - leave an AEN fetch / param op in flight (its 60 s thandle). # 3. While the reinit poll is cycling (dmesg keeps printing nothing new # but the callout keeps rescheduling), as root: # kldunload tws # 4. EXPECTED (vulnerable): within <= 5 s the softclock handler calls # tws_reinit()/tws_reset_cb()/tws_timeout() on freed memory -> # kernel panic (page fault in softirq / slab corruption), or callout # jumps into unmapped module text. # PATCHED (fix.diff): kldunload returns cleanly; no panic. # # On the audit QEMU guest there is no 13C1:1010 controller, so this script # only records the hardware absence (see run.log). set -e echo "== guest ==" uname -a echo "== LSI 3ware (0x13C1) controller present? ==" if pciconf -l 2>/dev/null | grep -q "13c1"; then echo "3ware controller present โ run the recipe above as root." else echo "NO 3ware controller (vendor 0x13C1) on this guest โ hardware-gated." kldload tws 2>&1 || true sysctl dev.tws 2>&1 | head -1 || true fi |