From 5889f06bd31d542766046faa6b17d957c08e1484 Mon Sep 17 00:00:00 2001 From: Li RongQing Date: Thu, 17 Dec 2015 21:30:02 +0800 Subject: watchdog: refuse to unload softdog module when its timer is running the softdog has static variables which are accessed if its timer is still running after the driver is unloaded. and lead to crash: $modprobe softdog $echo 1 >/dev/watchdog $modprobe -r softdog CPU 20 Unable to handle kernel paging request at virtual address Oops[#1]: CPU: 20 PID: 0 Comm: swapper/20 Not tainted 4.1.13-WR8.0.0.0_standard ... Modules linked in: [last unloaded: softdog] .... Call Trace: [] cascade+0x34/0xb0 [] run_timer_softirq+0x30c/0x368 [] __do_softirq+0x1ec/0x418 [] irq_exit+0x90/0x98 [] plat_irq_dispatch+0xa4/0x140 [] ret_from_irq+0x0/0x4 [] __r4k_wait+0x20/0x40 [] cpu_startup_entry+0x2a0/0x368 [] start_secondary+0x444/0x4d8 add the module ref when timer is running to avoid to unload the softdog module Signed-off-by: Li RongQing Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/softdog.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/watchdog') diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c index fe1e15137bf6..99a06f9e3930 100644 --- a/drivers/watchdog/softdog.c +++ b/drivers/watchdog/softdog.c @@ -86,6 +86,7 @@ static struct timer_list watchdog_ticktock = static void watchdog_fire(unsigned long data) { + module_put(THIS_MODULE); if (soft_noboot) pr_crit("Triggered - Reboot ignored\n"); else if (soft_panic) { @@ -104,13 +105,16 @@ static void watchdog_fire(unsigned long data) static int softdog_ping(struct watchdog_device *w) { - mod_timer(&watchdog_ticktock, jiffies+(w->timeout*HZ)); + if (!mod_timer(&watchdog_ticktock, jiffies+(w->timeout*HZ))) + __module_get(THIS_MODULE); return 0; } static int softdog_stop(struct watchdog_device *w) { - del_timer(&watchdog_ticktock); + if (del_timer(&watchdog_ticktock)) + module_put(THIS_MODULE); + return 0; } -- cgit v1.2.3-58-ga151