* [PATCH] rseq: Prevent self-preemption when granting a time slice extension
@ 2026-10-23 4:04 Yao Kai
2026-10-26 11:40 ` Peter Zijlstra
0 siblings, 1 reply; 2+ messages in thread
From: Yao Kai @ 2026-10-23 4:04 UTC (permalink / raw)
To: Thomas Gleixner, Peter Zijlstra, Mathieu Desnoyers
Cc: Ingo Molnar, Mark Rutland, linux-kernel, liuyongqiang13, Yao Kai, stable
__rseq_grant_slice_extension() makes the grant visible to user space and
then reads the clock to compute the expiry time before it clears the
pending reschedule request. This runs in the exit to user mode loop with
interrupts enabled.
Clocksource read functions are free to disable and enable preemption.
kvm_clock_read(), xen_clocksource_read() and the arm64 architected timer
counter accessors, which are used when a counter erratum workaround is
active, do so. With full or lazy preemption, when the request which
triggered the grant is a non-lazy TIF_NEED_RESCHED, e.g. a lazy request
upgraded by the scheduler tick, then preempt_enable_notrace() in the clock
read function schedules right away, e.g. in a KVM guest:
__schedule
preempt_schedule_notrace
preempt_schedule_notrace_thunk
kvm_clock_get_cycles
ktime_get_mono_fast_ns
irqentry_exit
asm_sysvec_apic_timer_interrupt
The task is preempted with the grant already handed out to user space,
i.e. in the middle of the critical section which the extension is supposed
to protect. The stale grant is cleaned up when the task goes back to user
space, so the damage is limited to the extension silently not working for
such preemptions on systems which use one of these clocksources.
Read the clock in the interrupt disabled section after the reschedule
request has been cleared.
Fixes: dfb630f548a7 ("rseq: Implement rseq_grant_slice_extension()")
Cc: stable@vger.kernel.org
Signed-off-by: Yao Kai <yaokai34@huawei.com>
---
include/linux/rseq_entry.h | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
index 31ce349ed42c..3e6a339175f8 100644
--- a/include/linux/rseq_entry.h
+++ b/include/linux/rseq_entry.h
@@ -174,8 +174,6 @@ static __always_inline bool __rseq_grant_slice_extension(bool work_pending)
rseq_stat_inc(rseq_stats.s_granted);
curr->rseq.slice.state.granted = true;
- /* Store expiry time for arming the timer on the way out */
- curr->rseq.slice.expires = data_race(rseq_slice_ext_nsecs) + ktime_get_mono_fast_ns();
/*
* This is racy against a remote CPU setting TIF_NEED_RESCHED in
* several ways:
@@ -222,6 +220,18 @@ static __always_inline bool __rseq_grant_slice_extension(bool work_pending)
scoped_guard(irq) {
clear_tsk_need_resched(curr);
clear_preempt_need_resched();
+ /*
+ * Store expiry time for arming the timer on the way out.
+ *
+ * Read the clock only after the reschedule request has been
+ * cleared and with interrupts disabled. Clocksource read
+ * functions, e.g. kvm_clock_read(), may disable and enable
+ * preemption, which would otherwise schedule right here on a
+ * pending request and void the grant which was just handed
+ * out to user space.
+ */
+ curr->rseq.slice.expires = data_race(rseq_slice_ext_nsecs) +
+ ktime_get_mono_fast_ns();
}
return true;
--
2.43.0
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] rseq: Prevent self-preemption when granting a time slice extension
2026-10-23 4:04 [PATCH] rseq: Prevent self-preemption when granting a time slice extension Yao Kai
@ 2026-10-26 11:40 ` Peter Zijlstra
0 siblings, 0 replies; 2+ messages in thread
From: Peter Zijlstra @ 2026-10-26 11:40 UTC (permalink / raw)
To: Yao Kai
Cc: Thomas Gleixner, Mathieu Desnoyers, Ingo Molnar, Mark Rutland,
linux-kernel, liuyongqiang13, stable
On Fri, Oct 23, 2026 at 12:04:39PM +0800, Yao Kai wrote:
> __rseq_grant_slice_extension() makes the grant visible to user space and
> then reads the clock to compute the expiry time before it clears the
> pending reschedule request. This runs in the exit to user mode loop with
> interrupts enabled.
>
> Clocksource read functions are free to disable and enable preemption.
> kvm_clock_read(), xen_clocksource_read() and the arm64 architected timer
> counter accessors, which are used when a counter erratum workaround is
> active, do so. With full or lazy preemption, when the request which
> triggered the grant is a non-lazy TIF_NEED_RESCHED, e.g. a lazy request
> upgraded by the scheduler tick, then preempt_enable_notrace() in the clock
> read function schedules right away, e.g. in a KVM guest:
>
> __schedule
> preempt_schedule_notrace
> preempt_schedule_notrace_thunk
> kvm_clock_get_cycles
> ktime_get_mono_fast_ns
> irqentry_exit
> asm_sysvec_apic_timer_interrupt
>
> The task is preempted with the grant already handed out to user space,
> i.e. in the middle of the critical section which the extension is supposed
> to protect. The stale grant is cleaned up when the task goes back to user
> space, so the damage is limited to the extension silently not working for
> such preemptions on systems which use one of these clocksources.
>
> Read the clock in the interrupt disabled section after the reschedule
> request has been cleared.
>
> Fixes: dfb630f548a7 ("rseq: Implement rseq_grant_slice_extension()")
> Cc: stable@vger.kernel.org
> Signed-off-by: Yao Kai <yaokai34@huawei.com>
> ---
> include/linux/rseq_entry.h | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/rseq_entry.h b/include/linux/rseq_entry.h
> index 31ce349ed42c..3e6a339175f8 100644
> --- a/include/linux/rseq_entry.h
> +++ b/include/linux/rseq_entry.h
> @@ -174,8 +174,6 @@ static __always_inline bool __rseq_grant_slice_extension(bool work_pending)
> rseq_stat_inc(rseq_stats.s_granted);
>
> curr->rseq.slice.state.granted = true;
> - /* Store expiry time for arming the timer on the way out */
> - curr->rseq.slice.expires = data_race(rseq_slice_ext_nsecs) + ktime_get_mono_fast_ns();
> /*
> * This is racy against a remote CPU setting TIF_NEED_RESCHED in
> * several ways:
> @@ -222,6 +220,18 @@ static __always_inline bool __rseq_grant_slice_extension(bool work_pending)
> scoped_guard(irq) {
> clear_tsk_need_resched(curr);
> clear_preempt_need_resched();
> + /*
> + * Store expiry time for arming the timer on the way out.
> + *
> + * Read the clock only after the reschedule request has been
> + * cleared and with interrupts disabled. Clocksource read
> + * functions, e.g. kvm_clock_read(), may disable and enable
> + * preemption, which would otherwise schedule right here on a
> + * pending request and void the grant which was just handed
> + * out to user space.
> + */
> + curr->rseq.slice.expires = data_race(rseq_slice_ext_nsecs) +
> + ktime_get_mono_fast_ns();
> }
> return true;
I am confused; even with this patch on, a tick that happens after
unsafe_put_user() can cause things to get rescheduled 'instantly'. That
preemption happens from irqentry_exit_cond_resched(), and needs no help
from any preempt_enable() usage.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-26 11:40 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-23 4:04 [PATCH] rseq: Prevent self-preemption when granting a time slice extension Yao Kai
2026-10-26 11:40 ` Peter Zijlstra
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®