| From 6bab4a8a1888729f17f4923cc5867e4674f66333 Mon Sep 17 00:00:00 2001 |
| From: Maxime Ripard <maxime.ripard@free-electrons.com> |
| Date: Tue, 18 Nov 2014 23:59:33 +0100 |
| Subject: clockevent: sun4i: Fix race condition in the probe code |
| |
| From: Maxime Ripard <maxime.ripard@free-electrons.com> |
| |
| commit 6bab4a8a1888729f17f4923cc5867e4674f66333 upstream. |
| |
| The interrupts were activated and the handler registered before the clockevent |
| was registered in the probe function. |
| |
| The interrupt handler, however, was making the assumption that the clockevent |
| device was registered. |
| |
| That could cause a null pointer dereference if the timer interrupt was firing |
| during this narrow window. |
| |
| Fix that by moving the clockevent registration before the interrupt is enabled. |
| |
| Reported-by: Roman Byshko <rbyshko@gmail.com> |
| Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> |
| Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/clocksource/sun4i_timer.c | 12 ++++++------ |
| 1 file changed, 6 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/clocksource/sun4i_timer.c |
| +++ b/drivers/clocksource/sun4i_timer.c |
| @@ -182,6 +182,12 @@ static void __init sun4i_timer_init(stru |
| /* Make sure timer is stopped before playing with interrupts */ |
| sun4i_clkevt_time_stop(0); |
| |
| + sun4i_clockevent.cpumask = cpu_possible_mask; |
| + sun4i_clockevent.irq = irq; |
| + |
| + clockevents_config_and_register(&sun4i_clockevent, rate, |
| + TIMER_SYNC_TICKS, 0xffffffff); |
| + |
| ret = setup_irq(irq, &sun4i_timer_irq); |
| if (ret) |
| pr_warn("failed to setup irq %d\n", irq); |
| @@ -189,12 +195,6 @@ static void __init sun4i_timer_init(stru |
| /* Enable timer0 interrupt */ |
| val = readl(timer_base + TIMER_IRQ_EN_REG); |
| writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); |
| - |
| - sun4i_clockevent.cpumask = cpu_possible_mask; |
| - sun4i_clockevent.irq = irq; |
| - |
| - clockevents_config_and_register(&sun4i_clockevent, rate, |
| - TIMER_SYNC_TICKS, 0xffffffff); |
| } |
| CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer", |
| sun4i_timer_init); |