rtc: ftrtc010: fix integer overflow in time calculation

In ftrtc010_rtc_read_time() and ftrtc010_rtc_set_time(), all
variables (offset, days, hour, min, sec) are u32. The expression
"days * 86400 + hour * 3600 + min * 60 + sec" is evaluated in
32-bit arithmetic, which silently wraps around for dates beyond
approximately year 2106 (U32_MAX / 86400 ≈ 49710 days).

In ftrtc010_rtc_read_time(), perform the addition in 32-bit
arithmetic first to preserve two's complement wrapping for negative
offsets, then cast the result to timeu64_t. In
ftrtc010_rtc_set_time(), cast individual u32 operands to timeu64_t
before multiplication to prevent overflow in the right-hand side
of the offset calculation.

Fixes: 1d61d2592c ("rtc: gemini/ftrtc010: rename driver and symbols")
Assisted-by: Sashiko AI [static analysis]
Signed-off-by: Liu Dalin <liudalin@kylinsec.com.cn>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Tested-by: Liu Dalin <liudalin@kylinsec.com.cn>
Link: https://patch.msgid.link/42C8FBD59AA34EA9+20260827080320.3351155-4-liudalin@kylinsec.com.cn
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
This commit is contained in:
Liu Dalin 2026-08-27 16:03:20 +08:00 committed by Alexandre Belloni
parent d41ee317c9
commit 32f04694fa

View File

@ -72,7 +72,7 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm)
days = readl(rtc->rtc_base + FTRTC010_RTC_DAYS);
offset = readl(rtc->rtc_base + FTRTC010_RTC_RECORD);
time = offset + days * 86400 + hour * 3600 + min * 60 + sec;
time = (timeu64_t)(offset + days * 86400 + hour * 3600 + min * 60 + sec);
rtc_time64_to_tm(time, tm);
@ -92,7 +92,8 @@ static int ftrtc010_rtc_set_time(struct device *dev, struct rtc_time *tm)
hour = readl(rtc->rtc_base + FTRTC010_RTC_HOUR);
day = readl(rtc->rtc_base + FTRTC010_RTC_DAYS);
offset = time - (day * 86400 + hour * 3600 + min * 60 + sec);
offset = time - ((timeu64_t)day * 86400 + (timeu64_t)hour * 3600 +
(timeu64_t)min * 60 + (timeu64_t)sec);
writel(offset, rtc->rtc_base + FTRTC010_RTC_RECORD);
writel(0x01, rtc->rtc_base + FTRTC010_RTC_CR);