Re: [patch V4 15/36] rseq: Record interrupt from user space

Mathieu Desnoyers
2025-09-09T13:53:33Z

On 2025-09-08 17:31, Thomas Gleixner wrote:
> For RSEQ the only relevant reason to inspect and eventually fixup (abort)
> user space critical sections is when user space was interrupted and the
> task was scheduled out.
>
> If the user to kernel entry was from a syscall no fixup is required. If
> user space invokes a syscall from a critical section it can keep the
> pieces as documented.
>
> This is only supported on architectures which utilize the generic entry
> code. If your architecture does not use it, bad luck.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>
> ---
> include/linux/irq-entry-common.h | 3 ++-
> include/linux/rseq.h | 16 +++++++++++-----
> include/linux/rseq_entry.h | 18 ++++++++++++++++++
> include/linux/rseq_types.h | 2 ++
> 4 files changed, 33 insertions(+), 6 deletions(-)
>
> --- a/include/linux/irq-entry-common.h
> +++ b/include/linux/irq-entry-common.h
> @@ -4,7 +4,7 @@
>
> #include <linux/context_tracking.h>
> #include <linux/kmsan.h>
> -#include <linux/rseq.h>
> +#include <linux/rseq_entry.h>
> #include <linux/static_call_types.h>
> #include <linux/syscalls.h>
> #include <linux/tick.h>
> @@ -281,6 +281,7 @@ static __always_inline void exit_to_user
> static __always_inline void irqentry_enter_from_user_mode(struct pt_regs *regs)
> {
> enter_from_user_mode(regs);
> + rseq_note_user_irq_entry();
> }
>
> /**
> --- a/include/linux/rseq.h
> +++ b/include/linux/rseq.h
> @@ -31,11 +31,17 @@ static inline void rseq_sched_switch_eve
>
> static __always_inline void rseq_exit_to_user_mode(void)
> {
> - if (IS_ENABLED(CONFIG_DEBUG_RSEQ)) {
> - if (WARN_ON_ONCE(current->rseq.event.has_rseq &&
> - current->rseq.event.events))
> - current->rseq.event.events = 0;
> - }
> + struct rseq_event *ev = &current->rseq.event;
> +
> + if (IS_ENABLED(CONFIG_DEBUG_RSEQ))
> + WARN_ON_ONCE(ev->sched_switch);

OK. Now I'm confused.

It is perfectly legal to issue a system call from userspace as long
as it's not from within an rseq critical section.

That system call can be scheduled out, and can set the ev->sched_switch.

This would cause the rseq_exit_to_user_mode from system call to
hit this.

What is disallowed is only issuing a system call from a rseq critical
section. The other parts of rseq (updates of cpu id and mm cid) still
have to happen when returning from a system call.

What am I missing ?

Thanks,

Mathieu

> +
> + /*
> + * Ensure that event (especially user_irq) is cleared when the
> + * interrupt did not result in a schedule and therefore the
> + * rseq processing did not clear it.
> + */
> + ev->events = 0;
> }
>
> /*
> --- /dev/null
> +++ b/include/linux/rseq_entry.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _LINUX_RSEQ_ENTRY_H
> +#define _LINUX_RSEQ_ENTRY_H
> +
> +#ifdef CONFIG_RSEQ
> +#include <linux/rseq.h>
> +
> +static __always_inline void rseq_note_user_irq_entry(void)
> +{
> + if (IS_ENABLED(CONFIG_GENERIC_IRQ_ENTRY))
> + current->rseq.event.user_irq = true;
> +}
> +
> +#else /* CONFIG_RSEQ */
> +static inline void rseq_note_user_irq_entry(void) { }
> +#endif /* !CONFIG_RSEQ */
> +
> +#endif /* _LINUX_RSEQ_ENTRY_H */
> --- a/include/linux/rseq_types.h
> +++ b/include/linux/rseq_types.h
> @@ -12,6 +12,7 @@ struct rseq;
> * @all: Compound to initialize and clear the data efficiently
> * @events: Compound to access events with a single load/store
> * @sched_switch: True if the task was scheduled out
> + * @user_irq: True on interrupt entry from user mode
> * @has_rseq: True if the task has a rseq pointer installed
> */
> struct rseq_event {
> @@ -22,6 +23,7 @@ struct rseq_event {
> u16 events;
> struct {
> u8 sched_switch;
> + u8 user_irq;
> };
> };
>
>

--
Mathieu Desnoyers
EfficiOS Inc.