diff options
author | Ales Novak <alnovak@suse.cz> | 2014-06-07 01:35:39 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-07 03:08:06 +0400 |
commit | ee1d90146815fdc8d653c558b327fff2acba041d (patch) | |
tree | ed7ce64394d3adcca0974b359b8a2166c360fb9d /drivers | |
parent | 3364d113c8209feee425b0f8a770b51e6132c43f (diff) | |
download | linux-ee1d90146815fdc8d653c558b327fff2acba041d.tar.xz |
drivers/rtc/interface.c: fix infinite loop in initializing the alarm
In __rtc_read_alarm(), if the alarm time retrieved by
rtc_read_alarm_internal() from the device contains invalid values (e.g.
month=2,mday=31) and the year not set (=-1), the initialization will
loop infinitely because the year-fixing loop expects the time being
invalid due to leap year.
Fix reduces the loop to the leap years and adds final validity check.
Signed-off-by: Ales Novak <alnovak@suse.cz>
Acked-by: Alessandro Zummo <a.zummo@towertech.it>
Reported-by: Jiri Bohac <jbohac@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/rtc/interface.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index c2eff6082363..5813fa52c3d4 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -292,7 +292,8 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year"); do { alarm->time.tm_year++; - } while (rtc_valid_tm(&alarm->time) != 0); + } while (!is_leap_year(alarm->time.tm_year + 1900) + && rtc_valid_tm(&alarm->time) != 0); break; default: @@ -300,7 +301,16 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) } done: - return 0; + err = rtc_valid_tm(&alarm->time); + + if (err) { + dev_warn(&rtc->dev, "invalid alarm value: %d-%d-%d %d:%d:%d\n", + alarm->time.tm_year + 1900, alarm->time.tm_mon + 1, + alarm->time.tm_mday, alarm->time.tm_hour, alarm->time.tm_min, + alarm->time.tm_sec); + } + + return err; } int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |