kernel/time/timekeeping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
From: Dennis Moshegov <dennis@xzync.uk>
Subject: [PATCH] timekeeping: Use data_race() and READ_ONCE() in
ktime_get_real_seconds()
On 64-bit architectures, ktime_get_real_seconds() directly returns
tk_core.timekeeper.xtime_sec without acquiring a seqlock. This lockless
read is an intentional design choice optimized for ultra-fast,
approximate timestamping paths where a minor 1-second discrepancy is
acceptable.
However, Kernel Concurrency Sanitizer (KCSAN) flags a data race here
because the timekeeper structure is updated concurrently via a bulk
structure copy inside timekeeping_update_from_shadow() during timer
interrupts.
Since the 64-bit read is naturally aligned and atomic at the hardware
level, this data race is benign and does not cause data tearing.
Annotate the read path using data_race() combined with READ_ONCE() to
prevent compiler optimization anomalies and suppress the KCSAN warning.
Reported-by: syzbot+72789cd1697965e714ca@syzkaller.appspotmail.com
Closes: https://syzkaller.appspotmail.com/bug?extid=72789cd1697965e714ca
Assisted-by: Gemini:3.5-flash
Signed-off-by: Dennis Moshegov <dennis@xzync.uk>
---
kernel/time/timekeeping.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 4fd3c70c1..b2e5a87da 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1153,7 +1153,7 @@ time64_t ktime_get_real_seconds(void)
time64_t ktime_get_real_seconds(void)
{
#if BITS_PER_LONG == 64
- return tk_core.timekeeper.xtime_sec;
+ return data_race(READ_ONCE(tk_core.timekeeper.xtime_sec));
#else
unsigned int seq;
time64_t seconds;
--
2.43.0
On Sat, May 30 2026 at 18:38, Dennis Moshegov wrote:
> From: Dennis Moshegov <dennis@xzync.uk>
> Subject: [PATCH] timekeeping: Use data_race() and READ_ONCE() in
> ktime_get_real_seconds()
>
> On 64-bit architectures, ktime_get_real_seconds() directly returns
> tk_core.timekeeper.xtime_sec without acquiring a seqlock. This lockless
> read is an intentional design choice optimized for ultra-fast,
> approximate timestamping paths where a minor 1-second discrepancy is
> acceptable.
>
> However, Kernel Concurrency Sanitizer (KCSAN) flags a data race here
> because the timekeeper structure is updated concurrently via a bulk
> structure copy inside timekeeping_update_from_shadow() during timer
> interrupts.
>
> Since the 64-bit read is naturally aligned and atomic at the hardware
> level, this data race is benign and does not cause data tearing.
> Annotate the read path using data_race() combined with READ_ONCE() to
> prevent compiler optimization anomalies and suppress the KCSAN warning.
>
> Reported-by: syzbot+72789cd1697965e714ca@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspotmail.com/bug?extid=72789cd1697965e714ca
> Assisted-by: Gemini:3.5-flash
> Signed-off-by: Dennis Moshegov <dennis@xzync.uk>
> ---
> kernel/time/timekeeping.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
> index 4fd3c70c1..b2e5a87da 100644
> --- a/kernel/time/timekeeping.c
> +++ b/kernel/time/timekeeping.c
> @@ -1153,7 +1153,7 @@ time64_t ktime_get_real_seconds(void)
> time64_t ktime_get_real_seconds(void)
> {
> #if BITS_PER_LONG == 64
> - return tk_core.timekeeper.xtime_sec;
> + return data_race(READ_ONCE(tk_core.timekeeper.xtime_sec));
Where is the corresponding WRITE_ONCE() and what guarantees that the
memcpy(), which updates the timekeeper, will not result in a copy with
a smaller granularity?
Just suppressing the warning w/o validating that there is no way for
store tearing to happen is not cutting it. Tell your AI buddy to make
his homework.
Thanks,
tglx
© 2016 - 2026 Red Hat, Inc.