DragonFlyBSD Kernel Audit
← dashboard
DF-0105

DT_CALLOUT_ARMED set before callout_reset creates enqueue/cancel race (panic or tq_callouts underflow + spurious UAF)

Summary

taskqueue_enqueue_timeout (subr_taskqueue.c:359-363): DT_CALLOUT_ARMED flag set + tq_callouts++ under TQ_LOCK (:359-360), then TQ_UNLOCK (:362) BEFORE callout_reset (:363). taskqueue_cancel_timeout does callout_stop BEFORE TQ_LOCK (:475) then clears flag+tq_callouts-- if set (:478-481). Race: T1(enqueue) sets flag+drop lock; T2(cancel) callout_stop returns 0 (not armed yet), takes TQ_LOCK sees flag set clears+tq_callouts--; T1 callout_reset arms it. When fires taskqueue_timeout_func KASSERT DT_CALLOUT_ARMED (:333) -> panic DEBUG. Production: underflow tq_callouts + re-enqueue cancelled task (:335-336) -> UAF if caller freed timeout_task after cancel (autofs.c:398-400 pattern). Window = instructions TQ_UNLOCK->callout_reset; requires concurrent enqueue_timeout+cancel_timeout same timeout_task. Fix: set DT_CALLOUT_ARMED only after callout_reset succeeds, OR gate cancel cleanup on callout_stop return value.