Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 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

+13 -8
+8 -3
include/linux/rseq.h
··· 7 7 #include <linux/preempt.h> 8 8 #include <linux/sched.h> 9 9 10 + #ifdef CONFIG_MEMBARRIER 11 + # define RSEQ_EVENT_GUARD irq 12 + #else 13 + # define RSEQ_EVENT_GUARD preempt 14 + #endif 15 + 10 16 /* 11 17 * Map the event mask on the user-space ABI enum rseq_cs_flags 12 18 * for direct mask checks. ··· 47 41 static inline void rseq_signal_deliver(struct ksignal *ksig, 48 42 struct pt_regs *regs) 49 43 { 50 - preempt_disable(); 51 - __set_bit(RSEQ_EVENT_SIGNAL_BIT, &current->rseq_event_mask); 52 - preempt_enable(); 44 + scoped_guard(RSEQ_EVENT_GUARD) 45 + __set_bit(RSEQ_EVENT_SIGNAL_BIT, &current->rseq_event_mask); 53 46 rseq_handle_notify_resume(ksig, regs); 54 47 } 55 48
+5 -5
kernel/rseq.c
··· 342 342 343 343 /* 344 344 * Load and clear event mask atomically with respect to 345 - * scheduler preemption. 345 + * scheduler preemption and membarrier IPIs. 346 346 */ 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 + } 351 351 352 352 return !!event_mask; 353 353 }