* [PATCH] rtc: class: Make the time32 hctosys limit configurable
@ 2026-09-14 21:25 Karl Mehltretter
2026-09-15 5:48 ` Arnd Bergmann
0 siblings, 1 reply; 4+ messages in thread
From: Karl Mehltretter @ 2026-09-14 21:25 UTC (permalink / raw)
To: Alexandre Belloni
Cc: Karl Mehltretter, linux-rtc, linux-kernel, Arnd Bergmann
On 32-bit systems with RTC_HCTOSYS enabled, rtc_hctosys() rejects
RTC dates whose seconds value exceeds INT_MAX, even when userspace
uses a 64-bit time_t. This leaves system time uninitialized by the RTC.
Commit b3a5ac42ab18 ("rtc: hctosys: Ensure system time doesn't overflow
time_t") introduced this limit to protect time32 userspace from future
RTC dates that can break boot. The same limit prevents systems with
time64 userspace from initializing the clock from valid post-2038 dates.
Add RTC_HCTOSYS_TIME32_LIMIT for 32-bit kernels, defaulting to y to
preserve the existing safeguard. Allow integrators to disable it once
their entire userspace, including init, supports post-2038 dates.
Warn on rejection with the RTC date and option name so users can
identify the cause and find the setting.
Keep the option independent of COMPAT_32BIT_TIME. Userspace with a
64-bit time_t may still need legacy syscalls for operations that do
not represent post-2038 dates.
Fixes: b3a5ac42ab18 ("rtc: hctosys: Ensure system time doesn't overflow time_t")
Link: https://lore.kernel.org/all/20220908115337.1604277-1-arnd@kernel.org/
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
---
Tested this exact patch on SAM9X75 Curiosity (32-bit ARM, rtc0),
using three full kernel builds and six powered warm boots:
TIME32_LIMIT COMPAT_32BIT_TIME RTC in 2026 RTC in 2040
y y hctosys=1 hctosys=0, epoch + 2 s
n y hctosys=1 hctosys=1, correct time
n n hctosys=1 hctosys=1, correct time
The default-limit 2040 boot logged the rejected date and
CONFIG_RTC_HCTOSYS_TIME32_LIMIT=y. The other boots did not warn.
Legacy clock_gettime and futex returned -ENOSYS with COMPAT_32BIT_TIME=n.
Tests used a minimal time64 initramfs without NTP. Current clocks and
all original boot files were restored after testing.
Host tests checked Kconfig defaults and dependencies, the INT_MAX
boundary and error paths.
drivers/rtc/Kconfig | 23 +++++++++++++++++++++++
drivers/rtc/class.c | 8 +++++---
2 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 05b9233b9418..a594c041bc35 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -30,6 +30,29 @@ config RTC_HCTOSYS
the value read from a specified RTC device. This is useful to avoid
unnecessary fsck runs at boot time, and to network better.
+config RTC_HCTOSYS_TIME32_LIMIT
+ bool "Reject RTC dates after the 2038 cutoff"
+ depends on RTC_HCTOSYS && !64BIT
+ default y
+ help
+ Reject RTC dates after 03:14:07 UTC on 19 January 2038 when
+ initializing the system clock. This preserves the existing
+ safeguard for userspace using a signed 32-bit time_t.
+
+ A rejected date leaves system time unchanged, normally near the
+ Unix epoch, and the RTC's hctosys sysfs attribute reads 0. Userspace
+ must supply the time if no other source has initialized it.
+
+ Disable this only if the entire userspace, including the init
+ system, supports dates beyond 2038. Otherwise, an invalid future
+ date in the RTC may prevent booting.
+
+ Disabling this check does not require disabling COMPAT_32BIT_TIME:
+ userspace with a 64-bit time_t may still use legacy system calls
+ for operations that do not represent dates beyond 2038.
+
+ If unsure, say Y.
+
config RTC_HCTOSYS_DEVICE
string "RTC used to set the system time"
depends on RTC_HCTOSYS
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 01ba04028f1f..18ea141ab8c2 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -72,12 +72,14 @@ static void rtc_hctosys(struct rtc_device *rtc)
tv64.tv_sec = rtc_tm_to_time64(&tm);
-#if BITS_PER_LONG == 32
- if (tv64.tv_sec > INT_MAX) {
+ if (IS_ENABLED(CONFIG_RTC_HCTOSYS_TIME32_LIMIT) &&
+ tv64.tv_sec > INT_MAX) {
+ dev_warn(rtc->dev.parent,
+ "hctosys: rejecting %ptR UTC due to CONFIG_RTC_HCTOSYS_TIME32_LIMIT=y\n",
+ &tm);
err = -ERANGE;
goto err_read;
}
-#endif
err = do_settimeofday64(&tv64);
base-commit: 587858367581b9c55c3690f4e63382ad622719d4
--
2.39.5 (Apple Git-154)
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] rtc: class: Make the time32 hctosys limit configurable
2026-09-14 21:25 [PATCH] rtc: class: Make the time32 hctosys limit configurable Karl Mehltretter
@ 2026-09-15 5:48 ` Arnd Bergmann
2026-09-15 22:37 ` Karl Mehltretter
0 siblings, 1 reply; 4+ messages in thread
From: Arnd Bergmann @ 2026-09-15 5:48 UTC (permalink / raw)
To: Karl Mehltretter, Alexandre Belloni; +Cc: linux-rtc, linux-kernel
On Mon, Sep 14, 2026, at 23:25, Karl Mehltretter wrote:
> On 32-bit systems with RTC_HCTOSYS enabled, rtc_hctosys() rejects
> RTC dates whose seconds value exceeds INT_MAX, even when userspace
> uses a 64-bit time_t. This leaves system time uninitialized by the RTC.
>
> Commit b3a5ac42ab18 ("rtc: hctosys: Ensure system time doesn't overflow
> time_t") introduced this limit to protect time32 userspace from future
> RTC dates that can break boot. The same limit prevents systems with
> time64 userspace from initializing the clock from valid post-2038 dates.
Hi Karl,
Thanks for revisiting this!
> Add RTC_HCTOSYS_TIME32_LIMIT for 32-bit kernels, defaulting to y to
> preserve the existing safeguard. Allow integrators to disable it once
> their entire userspace, including init, supports post-2038 dates.
> Warn on rejection with the RTC date and option name so users can
> identify the cause and find the setting.
>
> Keep the option independent of COMPAT_32BIT_TIME. Userspace with a
> 64-bit time_t may still need legacy syscalls for operations that do
> not represent post-2038 dates.
What about the reverse: if COMPAT_32BIT_TIME is disabled, I don't
see why we'd want to allow turning this on, so maybe
+config RTC_HCTOSYS_TIME32_LIMIT
+ bool "Reject RTC dates after the 2038 cutoff"
+ depends on RTC_HCTOSYS && !64BIT && !COMPAT_32BIT_TIME
[Technically it would also make sense to enable the option on 64-bit
kernels running 32-bit userspace, which some users do to reduce
memory usage. However, we never supported that case and I'd rather
not start now.]
Arnd
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] rtc: class: Make the time32 hctosys limit configurable
2026-09-15 5:48 ` Arnd Bergmann
@ 2026-09-15 22:37 ` Karl Mehltretter
2026-09-16 6:56 ` Arnd Bergmann
0 siblings, 1 reply; 4+ messages in thread
From: Karl Mehltretter @ 2026-09-15 22:37 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: Alexandre Belloni, linux-rtc, linux-kernel
On Tue, Sep 15, 2026 at 07:48:12AM +0100, Arnd Bergmann wrote:
> On Mon, Sep 14, 2026, at 23:25, Karl Mehltretter wrote:
> > On 32-bit systems with RTC_HCTOSYS enabled, rtc_hctosys() rejects
> > RTC dates whose seconds value exceeds INT_MAX, even when userspace
> > uses a 64-bit time_t. This leaves system time uninitialized by the RTC.
> >
> > Commit b3a5ac42ab18 ("rtc: hctosys: Ensure system time doesn't overflow
> > time_t") introduced this limit to protect time32 userspace from future
> > RTC dates that can break boot. The same limit prevents systems with
> > time64 userspace from initializing the clock from valid post-2038 dates.
>
> Hi Karl,
>
> What about the reverse: if COMPAT_32BIT_TIME is disabled, I don't
> see why we'd want to allow turning this on, so maybe
>
I tried this and found a case where the limit may still be useful
with COMPAT_32BIT_TIME=n. Glibc can use time64 kernel interfaces
for applications with a 32-bit time_t. Conversion to time32 fails
with EOVERFLOW when the date is out of range.
I tested a small clock_gettime() program using Debian glibc 2.41
on 32-bit ARM in QEMU, with identical kernel configurations and
initramfs. With RTC_HCTOSYS=y, COMPAT_32BIT_TIME=n and RTC in 2040:
Kernel System year time32 clock_gettime()
--------------------- ----------- ---------------------
Baseline 1970 success
Patch with dependency 2040 -1, errno=EOVERFLOW
The legacy clock_gettime syscall returned ENOSYS in both cases.
The same program built with a 64-bit time_t succeeded on both
kernels. Both builds also succeeded with the RTC in 2026. Both
kernels booted with time64 init.
Disabling legacy syscalls therefore does not establish that all
applications use a 64-bit time_t. The dependency would remove the
existing safeguard automatically and prevent restoring it without
re-enabling the legacy ABI.
I would prefer to preserve existing RTC date acceptance by default
and let integrators opt into later dates once their userspace is
ready. Keeping the posted settings would do that:
depends on RTC_HCTOSYS && !64BIT
default y
With RTC_HCTOSYS=y, for RTC dates beyond the cutoff:
D = don't care (y or n gives the same result).
Kernel denotes kernel bitness, regardless of userspace bitness.
With the patch as posted:
Kernel COMPAT_32BIT_TIME RTC_HCTOSYS_TIME32_LIMIT Allow past cutoff
------ ----------------- ------------------------ -----------------
32-bit D y (default) n
32-bit D n y
64-bit D n (unavailable) y
For reference, the baseline behaves as follows:
Kernel COMPAT_32BIT_TIME Allow past cutoff
------ ----------------- -----------------
32-bit D n
64-bit D y
Karl
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] rtc: class: Make the time32 hctosys limit configurable
2026-09-15 22:37 ` Karl Mehltretter
@ 2026-09-16 6:56 ` Arnd Bergmann
0 siblings, 0 replies; 4+ messages in thread
From: Arnd Bergmann @ 2026-09-16 6:56 UTC (permalink / raw)
To: Karl Mehltretter; +Cc: Alexandre Belloni, linux-rtc, linux-kernel
On Wed, Sep 16, 2026, at 00:37, Karl Mehltretter wrote:
> On Tue, Sep 15, 2026 at 07:48:12AM +0100, Arnd Bergmann wrote:
>> On Mon, Sep 14, 2026, at 23:25, Karl Mehltretter wrote:
>> > On 32-bit systems with RTC_HCTOSYS enabled, rtc_hctosys() rejects
>> > RTC dates whose seconds value exceeds INT_MAX, even when userspace
>> > uses a 64-bit time_t. This leaves system time uninitialized by the RTC.
>> >
>> > Commit b3a5ac42ab18 ("rtc: hctosys: Ensure system time doesn't overflow
>> > time_t") introduced this limit to protect time32 userspace from future
>> > RTC dates that can break boot. The same limit prevents systems with
>> > time64 userspace from initializing the clock from valid post-2038 dates.
>>
>> What about the reverse: if COMPAT_32BIT_TIME is disabled, I don't
>> see why we'd want to allow turning this on, so maybe
>
> I tried this and found a case where the limit may still be useful
> with COMPAT_32BIT_TIME=n. Glibc can use time64 kernel interfaces
> for applications with a 32-bit time_t. Conversion to time32 fails
> with EOVERFLOW when the date is out of range.
>
> I tested a small clock_gettime() program using Debian glibc 2.41
> on 32-bit ARM in QEMU, with identical kernel configurations and
> initramfs. With RTC_HCTOSYS=y, COMPAT_32BIT_TIME=n and RTC in 2040:
>
> Kernel System year time32 clock_gettime()
> --------------------- ----------- ---------------------
> Baseline 1970 success
> Patch with dependency 2040 -1, errno=EOVERFLOW
I think this is technically a bug in glibc: a task that calls the
time32 clock_gettime() is supposed to fail with
COMPAT_32BIT_TIME=n regardless of the date, according to the
original design. I understand that this is hard to do in
glibc based on how it deals with the three kernel variants
(time32 only v5.0 and older, time64-only with COMPAT_32BIT_TIME=n,
both present), but I still hope that we can one day do this
e.g. by having allowing glibc to be built without the time32
library interfaces to force a link failure.
> The legacy clock_gettime syscall returned ENOSYS in both cases.
> The same program built with a 64-bit time_t succeeded on both
> kernels. Both builds also succeeded with the RTC in 2026. Both
> kernels booted with time64 init.
>
> Disabling legacy syscalls therefore does not establish that all
> applications use a 64-bit time_t. The dependency would remove the
> existing safeguard automatically and prevent restoring it without
> re-enabling the legacy ABI.
I'm not following your logic here, what is the safeguard?
With a fixed C library, COMPAT_32BIT_TIME=n should act as a safeguard
to ensure that no interfaces can be used that limit time to y2038
and break unexpectedly in the future. The RTC_HCTOSYS interface
has so far always thrown a wrench into that because it still truncates
an important interface inside of the kernel. Your patch makes it
possible to do the right thing here, but one still has to know
that the Kconfig option exists and turn it off in order to
actually make it work. Since we have COMPAT_32BIT_TIME as a global
option already, it makes a lot of sense to actually use it here
as well.
Arnd
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-09-16 6:56 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-14 21:25 [PATCH] rtc: class: Make the time32 hctosys limit configurable Karl Mehltretter
2026-09-15 5:48 ` Arnd Bergmann
2026-09-15 22:37 ` Karl Mehltretter
2026-09-16 6:56 ` Arnd Bergmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®