Skip to content

Commit 6eb350a

Browse files
committed
rseq: Protect event mask against membarrier IPI
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: 2a36ab7 ("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
1 parent 76eeb9b commit 6eb350a

2 files changed

Lines changed: 13 additions & 8 deletions

File tree

include/linux/rseq.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
#include <linux/preempt.h>
88
#include <linux/sched.h>
99

10+
#ifdef CONFIG_MEMBARRIER
11+
# define RSEQ_EVENT_GUARD irq
12+
#else
13+
# define RSEQ_EVENT_GUARD preempt
14+
#endif
15+
1016
/*
1117
* Map the event mask on the user-space ABI enum rseq_cs_flags
1218
* for direct mask checks.
@@ -41,9 +47,8 @@ static inline void rseq_handle_notify_resume(struct ksignal *ksig,
4147
static inline void rseq_signal_deliver(struct ksignal *ksig,
4248
struct pt_regs *regs)
4349
{
44-
preempt_disable();
45-
__set_bit(RSEQ_EVENT_SIGNAL_BIT, &current->rseq_event_mask);
46-
preempt_enable();
50+
scoped_guard(RSEQ_EVENT_GUARD)
51+
__set_bit(RSEQ_EVENT_SIGNAL_BIT, &current->rseq_event_mask);
4752
rseq_handle_notify_resume(ksig, regs);
4853
}
4954

kernel/rseq.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -342,12 +342,12 @@ static int rseq_need_restart(struct task_struct *t, u32 cs_flags)
342342

343343
/*
344344
* Load and clear event mask atomically with respect to
345-
* scheduler preemption.
345+
* scheduler preemption and membarrier IPIs.
346346
*/
347-
preempt_disable();
348-
event_mask = t->rseq_event_mask;
349-
t->rseq_event_mask = 0;
350-
preempt_enable();
347+
scoped_guard(RSEQ_EVENT_GUARD) {
348+
event_mask = t->rseq_event_mask;
349+
t->rseq_event_mask = 0;
350+
}
351351

352352
return !!event_mask;
353353
}

0 commit comments

Comments
 (0)