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

Merge tag 'core-rseq-2025-09-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull rseq updates from Thomas Gleixner:
"Two fixes for RSEQ:

- Protect the event mask modification against the membarrier() IPI as
otherwise the RmW operation is unprotected and events might be lost

- Fix the weak symbol reference in rseq selftests

The current weak RSEQ symbols definitions which were added to allow
static linkage are not working correctly as they effectively
re-define the glibc symbols leading to multiple versions of the
symbols when compiled with -fno-common.

Mark them as 'extern' to convert them from weak symbol definitions
to weak symbol references. That works with static and dynamic
linkage independent of -fcommon and -fno-common"

* tag 'core-rseq-2025-09-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
rseq/selftests: Use weak symbol reference, not definition, to link with glibc
rseq: Protect event mask against membarrier IPI

+17 -12
+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 }
+4 -4
tools/testing/selftests/rseq/rseq.c
··· 40 40 * Define weak versions to play nice with binaries that are statically linked 41 41 * against a libc that doesn't support registering its own rseq. 42 42 */ 43 - __weak ptrdiff_t __rseq_offset; 44 - __weak unsigned int __rseq_size; 45 - __weak unsigned int __rseq_flags; 43 + extern __weak ptrdiff_t __rseq_offset; 44 + extern __weak unsigned int __rseq_size; 45 + extern __weak unsigned int __rseq_flags; 46 46 47 47 static const ptrdiff_t *libc_rseq_offset_p = &__rseq_offset; 48 48 static const unsigned int *libc_rseq_size_p = &__rseq_size; ··· 209 209 * libc not having registered a restartable sequence. Try to find the 210 210 * symbols if that's the case. 211 211 */ 212 - if (!*libc_rseq_size_p) { 212 + if (!libc_rseq_size_p || !*libc_rseq_size_p) { 213 213 libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset"); 214 214 libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size"); 215 215 libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");