]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
rseq: Protect event mask against membarrier IPI
authorThomas Gleixner <tglx@linutronix.de>
Thu, 16 Oct 2025 11:59:18 +0000 (07:59 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 19 Oct 2025 14:23:21 +0000 (16:23 +0200)
[ Upstream commit 6eb350a2233100a283f882c023e5ad426d0ed63b ]

rseq_need_restart() reads and clears task::rseq_event_mask with preemption
disabled to guard against the scheduler.

But membarrier() uses an IPI and sets the PREEMPT bit in the event mask
from the IPI, which leaves that RMW operation unprotected.

Use guard(irq) if CONFIG_MEMBARRIER is enabled to fix that.

Fixes: 2a36ab717e8f ("rseq/membarrier: Add MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: stable@vger.kernel.org
[ Applied changes to include/linux/sched.h instead of include/linux/rseq.h ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
include/linux/sched.h
kernel/rseq.c

index 4dc764f3d26f5d40696312d8c11a5127b2759db3..37ee1b1c9ed5f3dc43b255d2f3010f4c595b31e3 100644 (file)
@@ -2313,6 +2313,12 @@ enum rseq_event_mask {
        RSEQ_EVENT_MIGRATE      = (1U << RSEQ_EVENT_MIGRATE_BIT),
 };
 
+#ifdef CONFIG_MEMBARRIER
+# define RSEQ_EVENT_GUARD      irq
+#else
+# define RSEQ_EVENT_GUARD      preempt
+#endif
+
 static inline void rseq_set_notify_resume(struct task_struct *t)
 {
        if (t->rseq)
@@ -2331,9 +2337,8 @@ static inline void rseq_handle_notify_resume(struct ksignal *ksig,
 static inline void rseq_signal_deliver(struct ksignal *ksig,
                                       struct pt_regs *regs)
 {
-       preempt_disable();
-       __set_bit(RSEQ_EVENT_SIGNAL_BIT, &current->rseq_event_mask);
-       preempt_enable();
+       scoped_guard(RSEQ_EVENT_GUARD)
+               __set_bit(RSEQ_EVENT_SIGNAL_BIT, &current->rseq_event_mask);
        rseq_handle_notify_resume(ksig, regs);
 }
 
index 840927ac417b194213170bf499d027465d11bf37..2fea2782e179971fa5a51737761433943e5b04d7 100644 (file)
@@ -226,12 +226,12 @@ static int rseq_need_restart(struct task_struct *t, u32 cs_flags)
 
        /*
         * Load and clear event mask atomically with respect to
-        * scheduler preemption.
+        * scheduler preemption and membarrier IPIs.
         */
-       preempt_disable();
-       event_mask = t->rseq_event_mask;
-       t->rseq_event_mask = 0;
-       preempt_enable();
+       scoped_guard(RSEQ_EVENT_GUARD) {
+               event_mask = t->rseq_event_mask;
+               t->rseq_event_mask = 0;
+       }
 
        return !!event_mask;
 }