Commit 5889f06b authored by Li RongQing's avatar Li RongQing Committed by Wim Van Sebroeck

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:
   [<ffffffff801e142c>] cascade+0x34/0xb0
   [<ffffffff801e1964>] run_timer_softirq+0x30c/0x368
   [<ffffffff80181044>] __do_softirq+0x1ec/0x418
   [<ffffffff801815d0>] irq_exit+0x90/0x98
   [<ffffffff8010749c>] plat_irq_dispatch+0xa4/0x140
   [<ffffffff80152740>] ret_from_irq+0x0/0x4
   [<ffffffff801529e0>] __r4k_wait+0x20/0x40
   [<ffffffff801c2278>] cpu_startup_entry+0x2a0/0x368
   [<ffffffff8015fa64>] start_secondary+0x444/0x4d8

add the module ref when timer is running to avoid to unload the softdog
module
Signed-off-by: default avatarLi RongQing <roy.qing.li@gmail.com>
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
Signed-off-by: default avatarWim Van Sebroeck <wim@iguana.be>
parent 8d2fa171
...@@ -86,6 +86,7 @@ static struct timer_list watchdog_ticktock = ...@@ -86,6 +86,7 @@ static struct timer_list watchdog_ticktock =
static void watchdog_fire(unsigned long data) static void watchdog_fire(unsigned long data)
{ {
module_put(THIS_MODULE);
if (soft_noboot) if (soft_noboot)
pr_crit("Triggered - Reboot ignored\n"); pr_crit("Triggered - Reboot ignored\n");
else if (soft_panic) { else if (soft_panic) {
...@@ -104,13 +105,16 @@ static void watchdog_fire(unsigned long data) ...@@ -104,13 +105,16 @@ static void watchdog_fire(unsigned long data)
static int softdog_ping(struct watchdog_device *w) 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; return 0;
} }
static int softdog_stop(struct watchdog_device *w) static int softdog_stop(struct watchdog_device *w)
{ {
del_timer(&watchdog_ticktock); if (del_timer(&watchdog_ticktock))
module_put(THIS_MODULE);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment