summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAles Novak <alnovak@suse.cz>2014-06-06 14:35:39 -0700
committerJiri Slaby <jslaby@suse.cz>2014-08-26 14:12:25 +0200
commit9db8cb5a6fa96ef0637e55f66dd970e51224d99c (patch)
treeddb2adece6e4d755c6d096b9259886571c8c19ec
parent33751b9ed01ee46fd1c20cf8c42c396704d88b28 (diff)
drivers/rtc/interface.c: fix infinite loop in initializing the alarm
commit ee1d90146815fdc8d653c558b327fff2acba041d upstream. 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> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
-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 72c5cdbe0791..ff20d90ea8e7 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -290,7 +290,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:
@@ -298,7 +299,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)