diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-04-05 22:06:51 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-04-05 22:06:51 +0300 |
commit | d5ca32738f8fbd3632928929cccb5789d44be390 (patch) | |
tree | c6eb2661370812a11cdf46bf318d835f99a1663e | |
parent | e5adbd6ec480164fe30ee65c94426cb12d64bc99 (diff) | |
parent | 760a53768610d427990192b5cfdb71310e1373db (diff) | |
download | linux-d5ca32738f8fbd3632928929cccb5789d44be390.tar.xz |
Merge tag 'timers-urgent-2020-04-05' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer fixes from Thomas Gleixner:
"Two timer subsystem fixes:
- Prevent a use after free in the new lockdep state tracking for
hrtimers
- Add missing parenthesis in the VF pit timer driver"
* tag 'timers-urgent-2020-04-05' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
clocksource/drivers/timer-vf-pit: Add missing parenthesis
hrtimer: Don't dereference the hrtimer pointer after the callback
-rw-r--r-- | drivers/clocksource/timer-vf-pit.c | 2 | ||||
-rw-r--r-- | include/linux/irqflags.h | 27 | ||||
-rw-r--r-- | kernel/time/hrtimer.c | 5 |
3 files changed, 20 insertions, 14 deletions
diff --git a/drivers/clocksource/timer-vf-pit.c b/drivers/clocksource/timer-vf-pit.c index 7ad4a8b008c2..1a86a4e7e344 100644 --- a/drivers/clocksource/timer-vf-pit.c +++ b/drivers/clocksource/timer-vf-pit.c @@ -129,7 +129,7 @@ static int __init pit_clockevent_init(unsigned long rate, int irq) __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG); BUG_ON(request_irq(irq, pit_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, - "VF pit timer", &clockevent_pit); + "VF pit timer", &clockevent_pit)); clockevent_pit.cpumask = cpumask_of(0); clockevent_pit.irq = irq; diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h index ceca42de4438..61a9ced3aa50 100644 --- a/include/linux/irqflags.h +++ b/include/linux/irqflags.h @@ -58,16 +58,21 @@ do { \ } while (0) # define lockdep_hrtimer_enter(__hrtimer) \ - do { \ - if (!__hrtimer->is_hard) \ - current->irq_config = 1; \ - } while (0) - -# define lockdep_hrtimer_exit(__hrtimer) \ - do { \ - if (!__hrtimer->is_hard) \ +({ \ + bool __expires_hardirq = true; \ + \ + if (!__hrtimer->is_hard) { \ + current->irq_config = 1; \ + __expires_hardirq = false; \ + } \ + __expires_hardirq; \ +}) + +# define lockdep_hrtimer_exit(__expires_hardirq) \ + do { \ + if (!__expires_hardirq) \ current->irq_config = 0; \ - } while (0) + } while (0) # define lockdep_posixtimer_enter() \ do { \ @@ -102,8 +107,8 @@ do { \ # define lockdep_hardirq_exit() do { } while (0) # define lockdep_softirq_enter() do { } while (0) # define lockdep_softirq_exit() do { } while (0) -# define lockdep_hrtimer_enter(__hrtimer) do { } while (0) -# define lockdep_hrtimer_exit(__hrtimer) do { } while (0) +# define lockdep_hrtimer_enter(__hrtimer) false +# define lockdep_hrtimer_exit(__context) do { } while (0) # define lockdep_posixtimer_enter() do { } while (0) # define lockdep_posixtimer_exit() do { } while (0) # define lockdep_irq_work_enter(__work) do { } while (0) diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index d0a5ba37aff4..d89da1c7e005 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -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); |