hrtimer: Don't dereference the hrtimer pointer after the callback
A hrtimer can be released in its callback, but lockdep_hrtimer_exit()
dereferences the pointer after the callback returns, i.e. a potential use
after free.
Retrieve the context in which the hrtimer expires before the callback is
invoked and use it in lockdep_hrtimer_exit().
Fixes: 40db173965
("lockdep: Add hrtimer context tracing bits")
Reported-by: syzbot+62c155c276e580cfb606@syzkaller.appspotmail.com
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20200331201849.fkp2siy3vcdqvqlz@linutronix.de
This commit is contained in:

committed by
Thomas Gleixner

parent
42595ce90b
commit
73d20564e0
@@ -1480,6 +1480,7 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
|
||||
unsigned long flags) __must_hold(&cpu_base->lock)
|
||||
{
|
||||
enum hrtimer_restart (*fn)(struct hrtimer *);
|
||||
bool expires_in_hardirq;
|
||||
int restart;
|
||||
|
||||
lockdep_assert_held(&cpu_base->lock);
|
||||
@@ -1514,11 +1515,11 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
|
||||
*/
|
||||
raw_spin_unlock_irqrestore(&cpu_base->lock, flags);
|
||||
trace_hrtimer_expire_entry(timer, now);
|
||||
lockdep_hrtimer_enter(timer);
|
||||
expires_in_hardirq = lockdep_hrtimer_enter(timer);
|
||||
|
||||
restart = fn(timer);
|
||||
|
||||
lockdep_hrtimer_exit(timer);
|
||||
lockdep_hrtimer_exit(expires_in_hardirq);
|
||||
trace_hrtimer_expire_exit(timer);
|
||||
raw_spin_lock_irq(&cpu_base->lock);
|
||||
|
||||
|
Reference in New Issue
Block a user