| From 6b6d188aae79a630957aefd88ff5c42af6553ee3 Mon Sep 17 00:00:00 2001 |
| From: Stephen Boyd <swboyd@chromium.org> |
| Date: Thu, 9 Jan 2020 07:59:07 -0800 |
| Subject: alarmtimer: Unregister wakeup source when module get fails |
| |
| From: Stephen Boyd <swboyd@chromium.org> |
| |
| commit 6b6d188aae79a630957aefd88ff5c42af6553ee3 upstream. |
| |
| The alarmtimer_rtc_add_device() function creates a wakeup source and then |
| tries to grab a module reference. If that fails the function returns early |
| with an error code, but fails to remove the wakeup source. |
| |
| Cleanup this exit path so there is no dangling wakeup source, which is |
| named 'alarmtime' left allocated which will conflict with another RTC |
| device that may be registered later. |
| |
| Fixes: 51218298a25e ("alarmtimer: Ensure RTC module is not unloaded") |
| Signed-off-by: Stephen Boyd <swboyd@chromium.org> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Reviewed-by: Douglas Anderson <dianders@chromium.org> |
| Cc: stable@vger.kernel.org |
| Link: https://lore.kernel.org/r/20200109155910.907-2-swboyd@chromium.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| kernel/time/alarmtimer.c | 8 +++++--- |
| 1 file changed, 5 insertions(+), 3 deletions(-) |
| |
| --- a/kernel/time/alarmtimer.c |
| +++ b/kernel/time/alarmtimer.c |
| @@ -91,6 +91,7 @@ static int alarmtimer_rtc_add_device(str |
| unsigned long flags; |
| struct rtc_device *rtc = to_rtc_device(dev); |
| struct wakeup_source *__ws; |
| + int ret = 0; |
| |
| if (rtcdev) |
| return -EBUSY; |
| @@ -105,8 +106,8 @@ static int alarmtimer_rtc_add_device(str |
| spin_lock_irqsave(&rtcdev_lock, flags); |
| if (!rtcdev) { |
| if (!try_module_get(rtc->owner)) { |
| - spin_unlock_irqrestore(&rtcdev_lock, flags); |
| - return -1; |
| + ret = -1; |
| + goto unlock; |
| } |
| |
| rtcdev = rtc; |
| @@ -115,11 +116,12 @@ static int alarmtimer_rtc_add_device(str |
| ws = __ws; |
| __ws = NULL; |
| } |
| +unlock: |
| spin_unlock_irqrestore(&rtcdev_lock, flags); |
| |
| wakeup_source_unregister(__ws); |
| |
| - return 0; |
| + return ret; |
| } |
| |
| static inline void alarmtimer_rtc_timer_init(void) |