On 2022-10-06 06:26:04 [-0600], Jason A. Donenfeld wrote: > e) del_timer_sync() on line 5 is called, and its `base->running_timer != > timer` check is false, because of step (c). If `base->running_timer != timer` then the timer ('s callback) is not currently active/ running. Therefore it can be removed from the timer bucket (in case it is pending in the future). If `base->running_timer == timer` then the timer ('s callback) is currently active. del_timer_sync() will loop in cpu_relax() until the callback finished. And then try again. > f) `stack.timer` gets freed / goes out of scope. > > g) The callback scheduled from step (b) runs, and we have a UaF. > > That's, anyway, what I understand Sultan to have pointed out to me. In > looking at this closely, though, to write this email, I noticed that > add_timer_on() does set TIMER_MIGRATING, which lock_timer_base() spins > on. So actually, maybe this scenario should be accounted for? Sultan, do > you care to comment here? During TIMER_MIGRATING the del_timer_sync() caller will spin until the condition is over. So it can remove the timer from the right bucket and check if it is active vs the right bucket. > Jason Sebastian