[PATCH v2 3/3] rtc: ftrtc010: fix integer overflow in time calculation

Liu Dalin liudalin at kylinsec.com.cn
Wed Oct 7 19:10:17 PDT 2026


在 2026/10/2 18:59, Dan Carpenter 写道:
> Commit 8ef8e9839a23 ("rtc: ftrtc010: fix integer overflow in time
> calculation") from Aug 27, 2026 (linux-next), leads to the following
> Smatch static checker warning:
>
> 	drivers/rtc/rtc-ftrtc010.c:75 ftrtc010_rtc_read_time()
> 	warn: cast after binop
>
> On Thu, 27 Aug 2026 16:03:20 +0800 Liu Dalin <liudalin at kylinsec.com.cn> wrote:
>> 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: 1d61d2592c1f ("rtc: ftrtc010: Rename to Faraday FTRTC010")
>> Assisted-by: Sashiko AI [static analysis]
>> Signed-off-by: Liu Dalin <liudalin at kylinsec.com.cn>
>> ---
>>   drivers/rtc/rtc-ftrtc010.c | 5 +++--
>>   1 file changed, 3 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c
>> index 19e6333bfbab..b29c96be40f4 100644
>> --- a/drivers/rtc/rtc-ftrtc010.c
>> +++ b/drivers/rtc/rtc-ftrtc010.c
>> @@ -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);
> There isn't any point in doing the cast outside the parentheses.  The
> other chunk probably does it correctly.
>
> regards,
> dan carpenter
Thanks Dan for review and catching this issue.

Commit 8ef8e9839a23 is now in Alexandre Belloni's rtc subsystem tree
(https://git.kernel.org/abelloni/c/8ef8e9839a23), not yet in linux‑next 
or mainline.

You are right, the original commit 8ef8e9839a23 only tried to preserve u32
wrap‑around for the RECORD offset but had two problems:
1. It triggers smatch "cast after binop" warning.
2. More importantly, casting the wrapped u32 value to timeu64_t does zero
extension instead of sign extension, so negative offsets become large
positive values and break time calculation.

I will send a separate fixup patch addressing both issues: cast raw RECORD
u32 value to s32 for proper two's complement interpretation, then perform
all calculations in timeu64_t to avoid 32‑bit overflow.

Regards,
Liu Dalin
>>   
>>   	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);
>> -- 
>> 2.43.0
>>
>>



More information about the linux-arm-kernel mailing list