Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull rseq fixes from Thomas Gleixer: "A pile of rseq related fixups: - Prevent infinite recursion when delivering SIGSEGV - Remove the abort of rseq critical section on fork() as syscalls inside rseq critical sections are explicitely forbidden. So no point in doing the abort on the child. - Align the rseq structure on 32 bytes in the ARM selftest code. - Fix file permissions of the test script" * 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: rseq: Avoid infinite recursion when delivering SIGSEGV rseq/cleanup: Do not abort rseq c.s. in child on fork() rseq/selftests/arm: Align 'struct rseq_cs' on 32 bytes rseq/selftests: Make run_param_test.sh executablehifive-unleashed-5.1
commit
2ce413ec16
|
@ -544,7 +544,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||||
* Increment event counter and perform fixup for the pre-signal
|
* Increment event counter and perform fixup for the pre-signal
|
||||||
* frame.
|
* frame.
|
||||||
*/
|
*/
|
||||||
rseq_signal_deliver(regs);
|
rseq_signal_deliver(ksig, regs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up the stack frame
|
* Set up the stack frame
|
||||||
|
@ -666,7 +666,7 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
|
||||||
} else {
|
} else {
|
||||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||||
tracehook_notify_resume(regs);
|
tracehook_notify_resume(regs);
|
||||||
rseq_handle_notify_resume(regs);
|
rseq_handle_notify_resume(NULL, regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
|
|
@ -134,7 +134,7 @@ static void do_signal(struct task_struct *tsk)
|
||||||
/* Re-enable the breakpoints for the signal stack */
|
/* Re-enable the breakpoints for the signal stack */
|
||||||
thread_change_pc(tsk, tsk->thread.regs);
|
thread_change_pc(tsk, tsk->thread.regs);
|
||||||
|
|
||||||
rseq_signal_deliver(tsk->thread.regs);
|
rseq_signal_deliver(&ksig, tsk->thread.regs);
|
||||||
|
|
||||||
if (is32) {
|
if (is32) {
|
||||||
if (ksig.ka.sa.sa_flags & SA_SIGINFO)
|
if (ksig.ka.sa.sa_flags & SA_SIGINFO)
|
||||||
|
@ -170,7 +170,7 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
|
||||||
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
||||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||||
tracehook_notify_resume(regs);
|
tracehook_notify_resume(regs);
|
||||||
rseq_handle_notify_resume(regs);
|
rseq_handle_notify_resume(NULL, regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
user_enter();
|
user_enter();
|
||||||
|
|
|
@ -164,7 +164,7 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags)
|
||||||
if (cached_flags & _TIF_NOTIFY_RESUME) {
|
if (cached_flags & _TIF_NOTIFY_RESUME) {
|
||||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||||
tracehook_notify_resume(regs);
|
tracehook_notify_resume(regs);
|
||||||
rseq_handle_notify_resume(regs);
|
rseq_handle_notify_resume(NULL, regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cached_flags & _TIF_USER_RETURN_NOTIFY)
|
if (cached_flags & _TIF_USER_RETURN_NOTIFY)
|
||||||
|
|
|
@ -692,7 +692,7 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
|
||||||
* Increment event counter and perform fixup for the pre-signal
|
* Increment event counter and perform fixup for the pre-signal
|
||||||
* frame.
|
* frame.
|
||||||
*/
|
*/
|
||||||
rseq_signal_deliver(regs);
|
rseq_signal_deliver(ksig, regs);
|
||||||
|
|
||||||
/* Set up the stack frame */
|
/* Set up the stack frame */
|
||||||
if (is_ia32_frame(ksig)) {
|
if (is_ia32_frame(ksig)) {
|
||||||
|
|
|
@ -1799,20 +1799,22 @@ static inline void rseq_set_notify_resume(struct task_struct *t)
|
||||||
set_tsk_thread_flag(t, TIF_NOTIFY_RESUME);
|
set_tsk_thread_flag(t, TIF_NOTIFY_RESUME);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __rseq_handle_notify_resume(struct pt_regs *regs);
|
void __rseq_handle_notify_resume(struct ksignal *sig, struct pt_regs *regs);
|
||||||
|
|
||||||
static inline void rseq_handle_notify_resume(struct pt_regs *regs)
|
static inline void rseq_handle_notify_resume(struct ksignal *ksig,
|
||||||
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
if (current->rseq)
|
if (current->rseq)
|
||||||
__rseq_handle_notify_resume(regs);
|
__rseq_handle_notify_resume(ksig, regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void rseq_signal_deliver(struct pt_regs *regs)
|
static inline void rseq_signal_deliver(struct ksignal *ksig,
|
||||||
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
preempt_disable();
|
preempt_disable();
|
||||||
__set_bit(RSEQ_EVENT_SIGNAL_BIT, ¤t->rseq_event_mask);
|
__set_bit(RSEQ_EVENT_SIGNAL_BIT, ¤t->rseq_event_mask);
|
||||||
preempt_enable();
|
preempt_enable();
|
||||||
rseq_handle_notify_resume(regs);
|
rseq_handle_notify_resume(ksig, regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rseq_preempt() requires preemption to be disabled. */
|
/* rseq_preempt() requires preemption to be disabled. */
|
||||||
|
@ -1831,9 +1833,7 @@ static inline void rseq_migrate(struct task_struct *t)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If parent process has a registered restartable sequences area, the
|
* If parent process has a registered restartable sequences area, the
|
||||||
* child inherits. Only applies when forking a process, not a thread. In
|
* child inherits. Only applies when forking a process, not a thread.
|
||||||
* case a parent fork() in the middle of a restartable sequence, set the
|
|
||||||
* resume notifier to force the child to retry.
|
|
||||||
*/
|
*/
|
||||||
static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags)
|
static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags)
|
||||||
{
|
{
|
||||||
|
@ -1847,7 +1847,6 @@ static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags)
|
||||||
t->rseq_len = current->rseq_len;
|
t->rseq_len = current->rseq_len;
|
||||||
t->rseq_sig = current->rseq_sig;
|
t->rseq_sig = current->rseq_sig;
|
||||||
t->rseq_event_mask = current->rseq_event_mask;
|
t->rseq_event_mask = current->rseq_event_mask;
|
||||||
rseq_preempt(t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1864,10 +1863,12 @@ static inline void rseq_execve(struct task_struct *t)
|
||||||
static inline void rseq_set_notify_resume(struct task_struct *t)
|
static inline void rseq_set_notify_resume(struct task_struct *t)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static inline void rseq_handle_notify_resume(struct pt_regs *regs)
|
static inline void rseq_handle_notify_resume(struct ksignal *ksig,
|
||||||
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static inline void rseq_signal_deliver(struct pt_regs *regs)
|
static inline void rseq_signal_deliver(struct ksignal *ksig,
|
||||||
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static inline void rseq_preempt(struct task_struct *t)
|
static inline void rseq_preempt(struct task_struct *t)
|
||||||
|
|
|
@ -251,10 +251,10 @@ static int rseq_ip_fixup(struct pt_regs *regs)
|
||||||
* respect to other threads scheduled on the same CPU, and with respect
|
* respect to other threads scheduled on the same CPU, and with respect
|
||||||
* to signal handlers.
|
* to signal handlers.
|
||||||
*/
|
*/
|
||||||
void __rseq_handle_notify_resume(struct pt_regs *regs)
|
void __rseq_handle_notify_resume(struct ksignal *ksig, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct task_struct *t = current;
|
struct task_struct *t = current;
|
||||||
int ret;
|
int ret, sig;
|
||||||
|
|
||||||
if (unlikely(t->flags & PF_EXITING))
|
if (unlikely(t->flags & PF_EXITING))
|
||||||
return;
|
return;
|
||||||
|
@ -268,7 +268,8 @@ void __rseq_handle_notify_resume(struct pt_regs *regs)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
force_sig(SIGSEGV, t);
|
sig = ksig ? ksig->sig : 0;
|
||||||
|
force_sigsegv(sig, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_RSEQ
|
#ifdef CONFIG_DEBUG_RSEQ
|
||||||
|
|
|
@ -57,6 +57,7 @@ do { \
|
||||||
#define __RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, \
|
#define __RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, \
|
||||||
abort_label, version, flags, \
|
abort_label, version, flags, \
|
||||||
start_ip, post_commit_offset, abort_ip) \
|
start_ip, post_commit_offset, abort_ip) \
|
||||||
|
".balign 32\n\t" \
|
||||||
__rseq_str(table_label) ":\n\t" \
|
__rseq_str(table_label) ":\n\t" \
|
||||||
".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
|
".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
|
||||||
".word " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \
|
".word " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \
|
||||||
|
|
Loading…
Reference in New Issue