DragonFlyBSD Kernel Audit
DF-2679 / fix_iterations.log
← back to finding ↓ download raw
DF-2679 fix.diff iteration record (fix validation is part of the evidence)

v1 (initial): bus_topo_lock EXCL at make_device publish + all three
  devclass_delete_device call sites (incl. the device_set_devclass(0)
  probe-loop site); SHARED held across walk+fields+dispatch+SYSCTL_OUT
  in both readers.
  RESULT: kernel #1 (14:58:28) deadlocked under the identical stress:
    spin_lock_ex: AcpiOsWaitSemaphore, indefinite wait (58 secs)!
    ...
    ssleep() at ssleep+0x38e
    AcpiOsWaitSemaphore() ...
    AcpiUtAcquireMutex() ... AcpiNsGetNode() ...
    Debugger("panic")
  -> AB-BA between SHARED holders sleeping in copyout/dispatch and
     attach-side EXCL waiters under ACPI mutexes.

v2: make_device no longer locked; readers release before SYSCTL_OUT
  (strings snapshotted to locals under the lock).
  RESULT: kernel #2 (15:16:12) still deadlocked, with the exact cycle:
    AcpiOsWaitSemaphore() ... AcpiUtAcquireMutex()
    AcpiGetObjectInfo()
    acpi_child_pnpinfo_str_method()
    Debugger("panic")
  -> walker holds topo SHARED across bus_child_pnpinfo_str dispatch
     (needs ACPI namespace mutex) while an ACPI-side thread blocked on
     topo EXCL holds that mutex; the remaining EXCL site reachable under
     ACPI mutexes is device_probe_child()'s device_set_devclass(child,0)
     (called per failed probe inside attach/probe contexts).

v3 (final, in fix.diff): v2 minus the device_set_devclass(0) EXCL wrap
  (probe-loop hot path; the transient nameunit churn there is the
  pre-existing narrow race, not the demonstrated crash). EXCL remains
  only in device_delete_child's unpublish+free tail and device_detach's
  devclass_delete_device wrap; readers hold SHARED across
  walk+snapshot+dispatch only.