lkml.org 
[lkml]   [2020]   [Dec]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 279/453] watchdog: Fix potential dereferencing of null pointer
    Date
    From: Wang Wensheng <wangwensheng4@huawei.com>

    [ Upstream commit 6f733cb2e7db38f8141b14740bcde577844a03b7 ]

    A reboot notifier, which stops the WDT by calling the stop hook without
    any check, would be registered when we set WDOG_STOP_ON_REBOOT flag.

    Howerer we allow the WDT driver to omit the stop hook since commit
    "d0684c8a93549" ("watchdog: Make stop function optional") and provide
    a module parameter for user that controls the WDOG_STOP_ON_REBOOT flag
    in commit 9232c80659e94 ("watchdog: Add stop_on_reboot parameter to
    control reboot policy"). Together that commits make user potential to
    insert a watchdog driver that don't provide a stop hook but with the
    stop_on_reboot parameter set, then dereferencing of null pointer occurs
    on system reboot.

    Check the stop hook before registering the reboot notifier to fix the
    issue.

    Fixes: d0684c8a9354 ("watchdog: Make stop function optional")
    Signed-off-by: Wang Wensheng <wangwensheng4@huawei.com>
    Reviewed-by: Guenter Roeck <linux@roeck-us.net>
    Link: https://lore.kernel.org/r/20201109130512.28121-1-wangwensheng4@huawei.com
    Signed-off-by: Guenter Roeck <linux@roeck-us.net>
    Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/watchdog/watchdog_core.c | 22 +++++++++++++---------
    1 file changed, 13 insertions(+), 9 deletions(-)

    diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
    index 861daf4f37b28..faa46a666f4c5 100644
    --- a/drivers/watchdog/watchdog_core.c
    +++ b/drivers/watchdog/watchdog_core.c
    @@ -255,15 +255,19 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
    }

    if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status)) {
    - wdd->reboot_nb.notifier_call = watchdog_reboot_notifier;
    -
    - ret = register_reboot_notifier(&wdd->reboot_nb);
    - if (ret) {
    - pr_err("watchdog%d: Cannot register reboot notifier (%d)\n",
    - wdd->id, ret);
    - watchdog_dev_unregister(wdd);
    - ida_simple_remove(&watchdog_ida, id);
    - return ret;
    + if (!wdd->ops->stop)
    + pr_warn("watchdog%d: stop_on_reboot not supported\n", wdd->id);
    + else {
    + wdd->reboot_nb.notifier_call = watchdog_reboot_notifier;
    +
    + ret = register_reboot_notifier(&wdd->reboot_nb);
    + if (ret) {
    + pr_err("watchdog%d: Cannot register reboot notifier (%d)\n",
    + wdd->id, ret);
    + watchdog_dev_unregister(wdd);
    + ida_simple_remove(&watchdog_ida, id);
    + return ret;
    + }
    }
    }

    --
    2.27.0


    \
     
     \ /
      Last update: 2020-12-28 16:35    [W:4.090 / U:0.340 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site