forked from Minki/linux
powerpc: Remove broken GregorianDay()
GregorianDay() is supposed to calculate the day of the week (tm->tm_wday) for a given day/month/year. In that calcuation it indexed into an array called MonthOffset using tm->tm_mon-1. However tm_mon is zero-based, not one-based, so this is off-by-one. It also means that every January, GregoiranDay() will access element -1 of the MonthOffset array. It also doesn't appear to be a correct algorithm either: see in contrast kernel/time/timeconv.c's time_to_tm function. It's been broken forever, which suggests no-one in userland uses this. It looks like no-one in the kernel uses tm->tm_wday either (see e.g. drivers/rtc/rtc-ds1305.c:319). tm->tm_wday is conventionally set to -1 when not available in hardware so we can simply set it to -1 and drop the function. (There are over a dozen other drivers in drivers/rtc that do this.) Found using UBSAN. Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> Cc: Andrew Morton <akpm@linux-foundation.org> # as an example of what UBSan finds. Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Alexandre Belloni <alexandre.belloni@free-electrons.com> Cc: rtc-linux@googlegroups.com Signed-off-by: Daniel Axtens <dja@axtens.net> Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
5f337e3e5b
commit
00b912b0c8
@ -27,7 +27,6 @@ extern struct clock_event_device decrementer_clockevent;
|
||||
|
||||
struct rtc_time;
|
||||
extern void to_tm(int tim, struct rtc_time * tm);
|
||||
extern void GregorianDay(struct rtc_time *tm);
|
||||
extern void tick_broadcast_ipi_handler(void);
|
||||
|
||||
extern void generic_calibrate_decr(void);
|
||||
|
@ -1002,38 +1002,6 @@ static int month_days[12] = {
|
||||
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
||||
};
|
||||
|
||||
/*
|
||||
* This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
|
||||
*/
|
||||
void GregorianDay(struct rtc_time * tm)
|
||||
{
|
||||
int leapsToDate;
|
||||
int lastYear;
|
||||
int day;
|
||||
int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
|
||||
|
||||
lastYear = tm->tm_year - 1;
|
||||
|
||||
/*
|
||||
* Number of leap corrections to apply up to end of last year
|
||||
*/
|
||||
leapsToDate = lastYear / 4 - lastYear / 100 + lastYear / 400;
|
||||
|
||||
/*
|
||||
* This year is a leap year if it is divisible by 4 except when it is
|
||||
* divisible by 100 unless it is divisible by 400
|
||||
*
|
||||
* e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 was
|
||||
*/
|
||||
day = tm->tm_mon > 2 && leapyear(tm->tm_year);
|
||||
|
||||
day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] +
|
||||
tm->tm_mday;
|
||||
|
||||
tm->tm_wday = day % 7;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(GregorianDay);
|
||||
|
||||
void to_tm(int tim, struct rtc_time * tm)
|
||||
{
|
||||
register int i;
|
||||
@ -1064,9 +1032,9 @@ void to_tm(int tim, struct rtc_time * tm)
|
||||
tm->tm_mday = day + 1;
|
||||
|
||||
/*
|
||||
* Determine the day of week
|
||||
* No-one uses the day of the week.
|
||||
*/
|
||||
GregorianDay(tm);
|
||||
tm->tm_wday = -1;
|
||||
}
|
||||
EXPORT_SYMBOL(to_tm);
|
||||
|
||||
|
@ -77,7 +77,7 @@ void maple_get_rtc_time(struct rtc_time *tm)
|
||||
if ((tm->tm_year + 1900) < 1970)
|
||||
tm->tm_year += 100;
|
||||
|
||||
GregorianDay(tm);
|
||||
tm->tm_wday = -1;
|
||||
}
|
||||
|
||||
int maple_set_rtc_time(struct rtc_time *tm)
|
||||
|
@ -31,8 +31,7 @@ static void opal_to_tm(u32 y_m_d, u64 h_m_s_ms, struct rtc_time *tm)
|
||||
tm->tm_hour = bcd2bin((h_m_s_ms >> 56) & 0xff);
|
||||
tm->tm_min = bcd2bin((h_m_s_ms >> 48) & 0xff);
|
||||
tm->tm_sec = bcd2bin((h_m_s_ms >> 40) & 0xff);
|
||||
|
||||
GregorianDay(tm);
|
||||
tm->tm_wday = -1;
|
||||
}
|
||||
|
||||
unsigned long __init opal_get_boot_time(void)
|
||||
|
@ -40,7 +40,7 @@ static void opal_to_tm(u32 y_m_d, u64 h_m_s_ms, struct rtc_time *tm)
|
||||
tm->tm_min = bcd2bin((h_m_s_ms >> 48) & 0xff);
|
||||
tm->tm_sec = bcd2bin((h_m_s_ms >> 40) & 0xff);
|
||||
|
||||
GregorianDay(tm);
|
||||
tm->tm_wday = -1;
|
||||
}
|
||||
|
||||
static void tm_to_opal(struct rtc_time *tm, u32 *y_m_d, u64 *h_m_s_ms)
|
||||
|
Loading…
Reference in New Issue
Block a user