[PATCH] rtc: ftrtc010: fix negative offset handling and smatch warning

liudalin liudalin at kylinsec.com.cn
Thu Oct 8 05:24:44 PDT 2026


在 2026/10/8 19:59, Alexandre Belloni 写道:
> On 08/10/2026 19:37:32+0800, Liu Dalin wrote:
>> A prior attempted to fix the 32-bit arithmetic overflow by turning
>> the implicit u32-to-timeu64_t cast into an explicit one. However,
>> all calculations still happen in u32, inheriting the existing
>> negative offset sign-extension bug, and the explicit cast triggers
>> smatch "cast after binop" warning.
>>
> AI is lying to you, offset will never ever be negative.

Agreed, Thanks for review!!

with rtc_dev->range_min = (u64)days * 86400 + hour * 3600 + min * 60 + sec;
         rtc_dev->range_max = U32_MAX + rtc_dev->range_min;

offset will never ever be negative.

>
>> The FTRTC010 RECORD register stores a signed 32-bit two's complement
>> offset exposed through readl() as a u32. Casting the whole u32
>> expression result to timeu64_t performs zero extension, so negative
>> offsets become huge positive values.
>>
>> Fix it by casting offset to s32 first to correctly interpret the
>> two's complement sign, then promote all operands to timeu64_t so all
>> calculations are done in 64-bit space. days/hour/min/sec are
>> non-negative hardware counters, so promoting them directly to
>> timeu64_t is safe.
>>
>> Fixes: 1d61d2592c1f ("rtc: gemini/ftrtc010: rename driver and symbols")
>>
>> Signed-off-by: Liu Dalin <liudalin at kylinsec.com.cn>
>> ---
>>   drivers/rtc/rtc-ftrtc010.c | 3 ++-
>>   1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c
>> index b29c96be40f4..65fe1e872239 100644
>> --- a/drivers/rtc/rtc-ftrtc010.c
>> +++ b/drivers/rtc/rtc-ftrtc010.c
>> @@ -72,7 +72,8 @@ 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 = (timeu64_t)(offset + days * 86400 + hour * 3600 + min * 60 + sec);
>> +	time = (timeu64_t)(s32)offset + (timeu64_t)days * 86400 +
>> +	       (timeu64_t)hour * 3600 + (timeu64_t)min * 60 + (timeu64_t)sec;
>>   
>>   	rtc_time64_to_tm(time, tm);
>>   
>> -- 
>> 2.43.0
>>




More information about the linux-arm-kernel mailing list