Commit 6eb350a2 authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

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: 2a36ab71 ("rseq/membarrier: Add MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ")
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Reviewed-by: default avatarBoqun Feng <boqun.feng@gmail.com>
Reviewed-by: default avatarMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: stable@vger.kernel.org
parent 76eeb9b8
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -7,6 +7,12 @@
#include <linux/preempt.h>
#include <linux/sched.h>

#ifdef CONFIG_MEMBARRIER
# define RSEQ_EVENT_GUARD	irq
#else
# define RSEQ_EVENT_GUARD	preempt
#endif

/*
 * Map the event mask on the user-space ABI enum rseq_cs_flags
 * for direct mask checks.
@@ -41,9 +47,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();
	scoped_guard(RSEQ_EVENT_GUARD)
		__set_bit(RSEQ_EVENT_SIGNAL_BIT, &current->rseq_event_mask);
	preempt_enable();
	rseq_handle_notify_resume(ksig, regs);
}

+5 −5
Original line number Diff line number Diff line
@@ -342,12 +342,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();
	scoped_guard(RSEQ_EVENT_GUARD) {
		event_mask = t->rseq_event_mask;
		t->rseq_event_mask = 0;
	preempt_enable();
	}

	return !!event_mask;
}