Re: [tip: core/urgent] entry/rseq: Fix hard lockup on granted time slice extension

From: Thomas Gleixner

Date: Fri Aug 07 2026 - 17:15:38 EST


On Thu, Aug 06 2026 at 12:48, tip-bot wrote:
> In __exit_to_user_mode_loop(), TSE eligibility is checked while
> IRQs are enabled. Granting a TSE might involve rearming the
> hrtimers. However, hrtimer_rearm_deferred_tif() is expected to be
> called with IRQs disabled (see include/linux/hrtimer_rearm.h:17).

Groan. Can people please use proper words and not random made up
acronyms. This is not a SMS service. And this file reference is
more than pointless.

> Following the suggestion from Peter Zijlstra, fix this potential lockup
> by reflowing __exit_to_user_mode_loop() to only enable IRQs after the
> TSE check.

Which is broken.

> @@ -132,6 +132,8 @@ static __always_inline bool __rseq_grant_slice_extension(bool work_pending)
> union rseq_slice_state state;
> struct rseq __user *rseq;
>
> + lockdep_assert_irqs_disabled();
> +
> if (!rseq_slice_extension_enabled())
> return false;

Care to look what the code there does?

rseq = curr->rseq.usrptr;
scoped_user_rw_access(rseq, efault) {

That's user access which requires interrupts to be enabled.

Niels' original patch was correct.

To answer Peter's question from the V1 submission:

>> Thomas, previously we would call hrtimer_rearm_deferred() before
>> re-enabling IRQs, but here it slipped past. And while disabling it will
>> cure the splat, I'm thinking it makes sense to reflow
>> __exit_to_user_mode_loop() to instead delay enabling IRQs.

Yes, but then we consolidated all the schedule() hrtimer interaction and
got a benefit when schedule() was invoked directly on the way
out. That's why we ended up moving into into the success path
of rseq_grant_slice_extension() because that obviously skips schedule().

That's why we have hrtimer_rearm_deferred_user_irq() in
__exit_to_user_mode_prepare() _before_ invoking exit_to_user_mode_loop()
to ensure that one of the TIF_NEED_RESCHED bits is set. If not and if
TIF_HRTIMER_REARM is set, then the rearming happens right there with
interrupts still disabled.

If one of the TIF_NEED_RESCHED bits is set, then enabling interrupts
right on top of the loop is safe because any interrupt/exception entry
needs to check the bit as well.

So the thing [wm]e f*cked up royally was to invoke
hrtimer_rearm_deferred_tif() with interrupts enabled and that needs to
be fixed.

Of course all of this can be figured out from the copious amount of
comments which got added to explain all of this magic.

Thanks,

tglx