]> git.hungrycats.org Git - linux/commitdiff
drivers/rtc/interface.c: fix infinite loop in initializing the alarm
authorAles Novak <alnovak@suse.cz>
Fri, 6 Jun 2014 21:35:39 +0000 (14:35 -0700)
committerJiri Slaby <jslaby@suse.cz>
Tue, 26 Aug 2014 12:12:25 +0000 (14:12 +0200)
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>
drivers/rtc/interface.c

index 72c5cdbe0791afd2fed9a4779e5769c82c6b6ba3..ff20d90ea8e7a2ae92a5313b119138e6d5b696ba 100644 (file)
@@ -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)