* [PATCH] timekeeping: Use data_race() and READ_ONCE() in ktime_get_real_seconds() @ 2026-05-30 17:38 Dennis Moshegov 2026-06-02 9:46 ` Thomas Gleixner 0 siblings, 1 reply; 6+ messages in thread From: Dennis Moshegov @ 2026-05-30 17:38 UTC (permalink / raw) To: john.stultz, tglx; +Cc: linux-kernel 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 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] timekeeping: Use data_race() and READ_ONCE() in ktime_get_real_seconds() 2026-05-30 17:38 [PATCH] timekeeping: Use data_race() and READ_ONCE() in ktime_get_real_seconds() Dennis Moshegov @ 2026-06-02 9:46 ` Thomas Gleixner [not found] ` <CAGqVGMp6z7VHvD6YGhgAL+2mffvM7FoFY1F__Xa2-u98YZRYeQ@mail.gmail.com> 0 siblings, 1 reply; 6+ messages in thread From: Thomas Gleixner @ 2026-06-02 9:46 UTC (permalink / raw) To: Dennis Moshegov, john.stultz; +Cc: linux-kernel 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 ^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <CAGqVGMp6z7VHvD6YGhgAL+2mffvM7FoFY1F__Xa2-u98YZRYeQ@mail.gmail.com>]
[parent not found: <871peo9485.ffs@fw13>]
[parent not found: <CAGqVGMrdhhVdCOQxNLtFkrDbeeEytJiiY+=2D7VYMue0xDD8DQ@mail.gmail.com>]
* Re: [PATCH] timekeeping: Use data_race() and READ_ONCE() in ktime_get_real_seconds() [not found] ` <CAGqVGMrdhhVdCOQxNLtFkrDbeeEytJiiY+=2D7VYMue0xDD8DQ@mail.gmail.com> @ 2026-06-16 9:11 ` Dennis Moshegov 2026-06-21 13:17 ` Thomas Gleixner 0 siblings, 1 reply; 6+ messages in thread From: Dennis Moshegov @ 2026-06-16 9:11 UTC (permalink / raw) To: Thomas Gleixner, linux-kernel From: Dennis M <dennismoshegov@gmail.com> Subject: [PATCH v2] timekeeping: Use READ_ONCE/WRITE_ONCE for xtime_sec to prevent tearing The timekeeper update path uses a bulk memcpy() to synchronize the timekeeper structure, which is not guaranteed to be atomic. This allows for torn reads in ktime_get_real_seconds() on 64-bit systems, where the sequence counter protection is bypassed for performance. To prevent reading a torn 64-bit xtime_sec value, enforce atomic-like access by using WRITE_ONCE() for the critical field before the bulk memcpy() in timekeeping_update_from_shadow(). Correspondingly, use READ_ONCE() in ktime_get_real_seconds() to ensure a fresh, consistent load from memory. Reported-by: syzbot+72789cd1697965e714ca@syzkaller.appspotmail.com Closes: https://syzkaller.appspotmail.com/bug?extid=72789cd1697965e714ca Signed-off-by: Dennis Moshegov <dennis@xzync.uk> --- timekeeping.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/timekeeping.c b/timekeeping.c index c493a40..461a68e 100644 --- a/timekeeping.c +++ b/timekeeping.c @@ -826,6 +826,7 @@ static void timekeeping_update_from_shadow(struct tk_data *tkd, unsigned int act * the cacheline optimized data layout of the timekeeper and requires * another indirection. */ + WRITE_ONCE(tkd->timekeeper.xtime_secy, tk->xtime_sec); memcpy(&tkd->timekeeper, tk, sizeof(*tk)); write_seqcount_end(&tkd->seq); } @@ -1153,11 +1154,11 @@ time64_t ktime_get_real_seconds(void) unsigned int seq; if (IS_ENABLED(CONFIG_64BIT)) - return tk->xtime_sec; + return READ_ONCE(tk->xtime_sec); do { seq = read_seqcount_begin(&tk_core.seq); - seconds = tk->xtime_sec; + seconds = READ_ONCE(tk->xtime_sec); } while (read_seqcount_retry(&tk_core.seq, seq)); @@ -1179,7 +1180,7 @@ noinstr time64_t __ktime_get_real_seconds(void) { struct timekeeper *tk = &tk_core.timekeeper; - return tk->xtime_sec; + return READ_ONCE(tk->xtime_sec); } /** -- 2.53.0.windows.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] timekeeping: Use data_race() and READ_ONCE() in ktime_get_real_seconds() 2026-06-16 9:11 ` Dennis Moshegov @ 2026-06-21 13:17 ` Thomas Gleixner 2026-07-20 8:40 ` Dennis Moshegov 0 siblings, 1 reply; 6+ messages in thread From: Thomas Gleixner @ 2026-06-21 13:17 UTC (permalink / raw) To: Dennis Moshegov, linux-kernel On Tue, Jun 16 2026 at 10:11, Dennis Moshegov wrote: > From: Dennis M <dennismoshegov@gmail.com> > Subject: [PATCH v2] timekeeping: Use READ_ONCE/WRITE_ONCE for > xtime_sec to prevent tearing > > The timekeeper update path uses a bulk memcpy() to > synchronize the timekeeper structure, which is not guaranteed to be atomic. > This allows for torn reads in ktime_get_real_seconds() on 64-bit systems, > where the sequence counter protection is bypassed for performance. > > To prevent reading a torn 64-bit xtime_sec value, enforce atomic-like > access by using WRITE_ONCE() for the critical field before the bulk > memcpy() in timekeeping_update_from_shadow(). Correspondingly, use > READ_ONCE() in ktime_get_real_seconds() to ensure a fresh, consistent > load from memory. > > Reported-by: syzbot+72789cd1697965e714ca@syzkaller.appspotmail.com > Closes: https://syzkaller.appspotmail.com/bug?extid=72789cd1697965e714ca > Signed-off-by: Dennis Moshegov <dennis@xzync.uk> > --- > timekeeping.c | 7 ++++--- > 1 file changed, 4 insertions(+), 3 deletions(-) > > diff --git a/timekeeping.c b/timekeeping.c > index c493a40..461a68e 100644 > --- a/timekeeping.c > +++ b/timekeeping.c You need to create the patch in the top level directory so that this becomes a/kernel/time/timekeeping.c > @@ -826,6 +826,7 @@ static void timekeeping_update_from_shadow(struct > tk_data *tkd, unsigned int act There is a line break after 'struct', which makes the patch malformed and it can't be applied as is. Thanks, tglx ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] timekeeping: Use data_race() and READ_ONCE() in ktime_get_real_seconds() 2026-06-21 13:17 ` Thomas Gleixner @ 2026-07-20 8:40 ` Dennis Moshegov 2026-07-20 14:03 ` Thomas Gleixner 0 siblings, 1 reply; 6+ messages in thread From: Dennis Moshegov @ 2026-07-20 8:40 UTC (permalink / raw) To: Thomas Gleixner; +Cc: linux-kernel From: Dennis M <dennismoshegov@gmail.com> Subject: [PATCH v3] timekeeping: Use READ_ONCE/WRITE_ONCE for xtime_sec to prevent tearing The timekeeper update path uses a bulk memcpy() to synchronize the timekeeper structure, which is not guaranteed to be atomic. This allows for torn reads in ktime_get_real_seconds() on 64-bit systems, where the sequence counter protection is bypassed for performance. To prevent reading a torn 64-bit xtime_sec value, enforce atomic-like access by using WRITE_ONCE() for the critical field before the bulk memcpy() in timekeeping_update_from_shadow(). Correspondingly, use READ_ONCE() in ktime_get_real_seconds() to ensure a fresh, consistent load from memory. Reported-by: syzbot+72789cd1697965e714ca@syzkaller.appspotmail.com Closes: https://syzkaller.appspotmail.com/bug?extid=72789cd1697965e714ca Signed-off-by: Dennis Moshegov <dennis@xzync.uk> --- timekeeping.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index c493a40..461a68e 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -826,6 +826,7 @@ static void timekeeping_update_from_shadow(struct tk_data *tkd, unsigned int action) * the cacheline optimized data layout of the timekeeper and requires * another indirection. */ + WRITE_ONCE(tkd->timekeeper.xtime_secy, tk->xtime_sec); memcpy(&tkd->timekeeper, tk, sizeof(*tk)); write_seqcount_end(&tkd->seq); } @@ -1153,11 +1154,11 @@ time64_t ktime_get_real_seconds(void) unsigned int seq; if (IS_ENABLED(CONFIG_64BIT)) - return tk->xtime_sec; + return READ_ONCE(tk->xtime_sec); do { seq = read_seqcount_begin(&tk_core.seq); - seconds = tk->xtime_sec; + seconds = READ_ONCE(tk->xtime_sec); } while (read_seqcount_retry(&tk_core.seq, seq)); @@ -1179,7 +1180,7 @@ noinstr time64_t __ktime_get_real_seconds(void) { struct timekeeper *tk = &tk_core.timekeeper; - return tk->xtime_sec; + return READ_ONCE(tk->xtime_sec); } /** -- 2.53.0.windows.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] timekeeping: Use data_race() and READ_ONCE() in ktime_get_real_seconds() 2026-07-20 8:40 ` Dennis Moshegov @ 2026-07-20 14:03 ` Thomas Gleixner 0 siblings, 0 replies; 6+ messages in thread From: Thomas Gleixner @ 2026-07-20 14:03 UTC (permalink / raw) To: Dennis Moshegov; +Cc: linux-kernel On Mon, Jul 20 2026 at 09:40, Dennis Moshegov wrote: > From: Dennis M <dennismoshegov@gmail.com> This from line mail address is not matching the > Subject: [PATCH v3] timekeeping: Use READ_ONCE/WRITE_ONCE for > xtime_sec to prevent tearing > > The timekeeper update path uses a bulk memcpy() to > synchronize the timekeeper structure, which is not guaranteed to be atomic. > This allows for torn reads in ktime_get_real_seconds() on 64-bit systems, > where the sequence counter protection is bypassed for performance. > > To prevent reading a torn 64-bit xtime_sec value, enforce atomic-like > access by using WRITE_ONCE() for the critical field before the bulk > memcpy() in timekeeping_update_from_shadow(). Correspondingly, use > READ_ONCE() in ktime_get_real_seconds() to ensure a fresh, consistent > load from memory. > > Reported-by: syzbot+72789cd1697965e714ca@syzkaller.appspotmail.com > Closes: https://syzkaller.appspotmail.com/bug?extid=72789cd1697965e714ca > Signed-off-by: Dennis Moshegov <dennis@xzync.uk> one used here. Please make your mind up which of your personalities you awant to use. > --- > timekeeping.c | 7 ++++--- > 1 file changed, 4 insertions(+), 3 deletions(-) > > diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c > index c493a40..461a68e 100644 > --- a/kernel/time/timekeeping.c > +++ b/kernel/time/timekeeping.c > @@ -826,6 +826,7 @@ static void timekeeping_update_from_shadow(struct > tk_data *tkd, unsigned int action) > * the cacheline optimized data layout of the timekeeper and requires > * another indirection. > */ > + WRITE_ONCE(tkd->timekeeper.xtime_secy, tk->xtime_sec); > memcpy(&tkd->timekeeper, tk, sizeof(*tk)); > write_seqcount_end(&tkd->seq); Again you used copy & paste to get the patch into your mail client or imported it and gmail mangled it. patching file kernel/time/timekeeping.c patch: **** malformed patch at line 34: tk_data *tkd, unsigned int action) See Documentation/process/email-clients.rst The only known way to send patches with the gmail web client is as attachment, but that's a pain for reviewing, replying and applying. But you can use git send-email with gmail smtp and that will do the right thing. Thanks, tglx ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-07-20 14:03 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-30 17:38 [PATCH] timekeeping: Use data_race() and READ_ONCE() in ktime_get_real_seconds() Dennis Moshegov
2026-06-02 9:46 ` Thomas Gleixner
[not found] ` <CAGqVGMp6z7VHvD6YGhgAL+2mffvM7FoFY1F__Xa2-u98YZRYeQ@mail.gmail.com>
[not found] ` <871peo9485.ffs@fw13>
[not found] ` <CAGqVGMrdhhVdCOQxNLtFkrDbeeEytJiiY+=2D7VYMue0xDD8DQ@mail.gmail.com>
2026-06-16 9:11 ` Dennis Moshegov
2026-06-21 13:17 ` Thomas Gleixner
2026-07-20 8:40 ` Dennis Moshegov
2026-07-20 14:03 ` Thomas Gleixner
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.