Commit 2ce413ec authored by Linus Torvalds's avatar Linus Torvalds

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 executable
parents 64dd7655 784e0300
...@@ -544,7 +544,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, &current->rseq_event_mask); __set_bit(RSEQ_EVENT_SIGNAL_BIT, &current->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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 { \ ...@@ -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" \
......
File mode changed from 100644 to 100755
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment