aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/interface.c
diff options
context:
space:
mode:
authorAles Novak <alnovak@suse.cz>2014-06-06 17:35:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-06 19:08:06 -0400
commitee1d90146815fdc8d653c558b327fff2acba041d (patch)
treeed7ce64394d3adcca0974b359b8a2166c360fb9d /drivers/rtc/interface.c
parent3364d113c8209feee425b0f8a770b51e6132c43f (diff)
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/rtc/interface.c')
-rw-r--r--drivers/rtc/interface.c14
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)
292 dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year"); 292 dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year");
293 do { 293 do {
294 alarm->time.tm_year++; 294 alarm->time.tm_year++;
295 } while (rtc_valid_tm(&alarm->time) != 0); 295 } while (!is_leap_year(alarm->time.tm_year + 1900)
296 && rtc_valid_tm(&alarm->time) != 0);
296 break; 297 break;
297 298
298 default: 299 default:
@@ -300,7 +301,16 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
300 } 301 }
301 302
302done: 303done:
303 return 0; 304 err = rtc_valid_tm(&alarm->time);
305
306 if (err) {
307 dev_warn(&rtc->dev, "invalid alarm value: %d-%d-%d %d:%d:%d\n",
308 alarm->time.tm_year + 1900, alarm->time.tm_mon + 1,
309 alarm->time.tm_mday, alarm->time.tm_hour, alarm->time.tm_min,
310 alarm->time.tm_sec);
311 }
312
313 return err;
304} 314}
305 315
306int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) 316int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)