diff options
| -rw-r--r-- | arch/arm/kernel/signal.c | 4 | ||||
| -rw-r--r-- | arch/powerpc/kernel/signal.c | 4 | ||||
| -rw-r--r-- | arch/x86/entry/common.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/signal.c | 2 | ||||
| -rw-r--r-- | include/linux/sched.h | 23 | ||||
| -rw-r--r-- | kernel/rseq.c | 7 | ||||
| -rw-r--r-- | tools/testing/selftests/rseq/rseq-arm.h | 1 | ||||
| -rwxr-xr-x[-rw-r--r--] | tools/testing/selftests/rseq/run_param_test.sh | 0 |
8 files changed, 23 insertions, 20 deletions
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index f09e9d66d605..dec130e7078c 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
| @@ -544,7 +544,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) | |||
| 544 | * Increment event counter and perform fixup for the pre-signal | 544 | * Increment event counter and perform fixup for the pre-signal |
| 545 | * frame. | 545 | * frame. |
| 546 | */ | 546 | */ |
| 547 | rseq_signal_deliver(regs); | 547 | rseq_signal_deliver(ksig, regs); |
| 548 | 548 | ||
| 549 | /* | 549 | /* |
| 550 | * Set up the stack frame | 550 | * Set up the stack frame |
| @@ -666,7 +666,7 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) | |||
| 666 | } else { | 666 | } else { |
| 667 | clear_thread_flag(TIF_NOTIFY_RESUME); | 667 | clear_thread_flag(TIF_NOTIFY_RESUME); |
| 668 | tracehook_notify_resume(regs); | 668 | tracehook_notify_resume(regs); |
| 669 | rseq_handle_notify_resume(regs); | 669 | rseq_handle_notify_resume(NULL, regs); |
| 670 | } | 670 | } |
| 671 | } | 671 | } |
| 672 | local_irq_disable(); | 672 | local_irq_disable(); |
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 17fe4339ba59..b3e8db376ecd 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
| @@ -134,7 +134,7 @@ static void do_signal(struct task_struct *tsk) | |||
| 134 | /* Re-enable the breakpoints for the signal stack */ | 134 | /* Re-enable the breakpoints for the signal stack */ |
| 135 | thread_change_pc(tsk, tsk->thread.regs); | 135 | thread_change_pc(tsk, tsk->thread.regs); |
| 136 | 136 | ||
| 137 | rseq_signal_deliver(tsk->thread.regs); | 137 | rseq_signal_deliver(&ksig, tsk->thread.regs); |
| 138 | 138 | ||
| 139 | if (is32) { | 139 | if (is32) { |
| 140 | if (ksig.ka.sa.sa_flags & SA_SIGINFO) | 140 | 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 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 170 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
| 171 | clear_thread_flag(TIF_NOTIFY_RESUME); | 171 | clear_thread_flag(TIF_NOTIFY_RESUME); |
| 172 | tracehook_notify_resume(regs); | 172 | tracehook_notify_resume(regs); |
| 173 | rseq_handle_notify_resume(regs); | 173 | rseq_handle_notify_resume(NULL, regs); |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | user_enter(); | 176 | user_enter(); |
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 92190879b228..3b2490b81918 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c | |||
| @@ -164,7 +164,7 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags) | |||
| 164 | if (cached_flags & _TIF_NOTIFY_RESUME) { | 164 | if (cached_flags & _TIF_NOTIFY_RESUME) { |
| 165 | clear_thread_flag(TIF_NOTIFY_RESUME); | 165 | clear_thread_flag(TIF_NOTIFY_RESUME); |
| 166 | tracehook_notify_resume(regs); | 166 | tracehook_notify_resume(regs); |
| 167 | rseq_handle_notify_resume(regs); | 167 | rseq_handle_notify_resume(NULL, regs); |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | if (cached_flags & _TIF_USER_RETURN_NOTIFY) | 170 | if (cached_flags & _TIF_USER_RETURN_NOTIFY) |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 445ca11ff863..92a3b312a53c 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
| @@ -692,7 +692,7 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs) | |||
| 692 | * Increment event counter and perform fixup for the pre-signal | 692 | * Increment event counter and perform fixup for the pre-signal |
| 693 | * frame. | 693 | * frame. |
| 694 | */ | 694 | */ |
| 695 | rseq_signal_deliver(regs); | 695 | rseq_signal_deliver(ksig, regs); |
| 696 | 696 | ||
| 697 | /* Set up the stack frame */ | 697 | /* Set up the stack frame */ |
| 698 | if (is_ia32_frame(ksig)) { | 698 | if (is_ia32_frame(ksig)) { |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 87bf02d93a27..9256118bd40c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -1799,20 +1799,22 @@ static inline void rseq_set_notify_resume(struct task_struct *t) | |||
| 1799 | set_tsk_thread_flag(t, TIF_NOTIFY_RESUME); | 1799 | set_tsk_thread_flag(t, TIF_NOTIFY_RESUME); |
| 1800 | } | 1800 | } |
| 1801 | 1801 | ||
| 1802 | void __rseq_handle_notify_resume(struct pt_regs *regs); | 1802 | void __rseq_handle_notify_resume(struct ksignal *sig, struct pt_regs *regs); |
| 1803 | 1803 | ||
| 1804 | static inline void rseq_handle_notify_resume(struct pt_regs *regs) | 1804 | static inline void rseq_handle_notify_resume(struct ksignal *ksig, |
| 1805 | struct pt_regs *regs) | ||
| 1805 | { | 1806 | { |
| 1806 | if (current->rseq) | 1807 | if (current->rseq) |
| 1807 | __rseq_handle_notify_resume(regs); | 1808 | __rseq_handle_notify_resume(ksig, regs); |
| 1808 | } | 1809 | } |
| 1809 | 1810 | ||
| 1810 | static inline void rseq_signal_deliver(struct pt_regs *regs) | 1811 | static inline void rseq_signal_deliver(struct ksignal *ksig, |
| 1812 | struct pt_regs *regs) | ||
| 1811 | { | 1813 | { |
| 1812 | preempt_disable(); | 1814 | preempt_disable(); |
| 1813 | __set_bit(RSEQ_EVENT_SIGNAL_BIT, ¤t->rseq_event_mask); | 1815 | __set_bit(RSEQ_EVENT_SIGNAL_BIT, ¤t->rseq_event_mask); |
| 1814 | preempt_enable(); | 1816 | preempt_enable(); |
| 1815 | rseq_handle_notify_resume(regs); | 1817 | rseq_handle_notify_resume(ksig, regs); |
| 1816 | } | 1818 | } |
| 1817 | 1819 | ||
| 1818 | /* rseq_preempt() requires preemption to be disabled. */ | 1820 | /* rseq_preempt() requires preemption to be disabled. */ |
| @@ -1831,9 +1833,7 @@ static inline void rseq_migrate(struct task_struct *t) | |||
| 1831 | 1833 | ||
| 1832 | /* | 1834 | /* |
| 1833 | * If parent process has a registered restartable sequences area, the | 1835 | * If parent process has a registered restartable sequences area, the |
| 1834 | * child inherits. Only applies when forking a process, not a thread. In | 1836 | * child inherits. Only applies when forking a process, not a thread. |
| 1835 | * case a parent fork() in the middle of a restartable sequence, set the | ||
| 1836 | * resume notifier to force the child to retry. | ||
| 1837 | */ | 1837 | */ |
| 1838 | static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags) | 1838 | static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags) |
| 1839 | { | 1839 | { |
| @@ -1847,7 +1847,6 @@ static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags) | |||
| 1847 | t->rseq_len = current->rseq_len; | 1847 | t->rseq_len = current->rseq_len; |
| 1848 | t->rseq_sig = current->rseq_sig; | 1848 | t->rseq_sig = current->rseq_sig; |
| 1849 | t->rseq_event_mask = current->rseq_event_mask; | 1849 | t->rseq_event_mask = current->rseq_event_mask; |
| 1850 | rseq_preempt(t); | ||
| 1851 | } | 1850 | } |
| 1852 | } | 1851 | } |
| 1853 | 1852 | ||
| @@ -1864,10 +1863,12 @@ static inline void rseq_execve(struct task_struct *t) | |||
| 1864 | static inline void rseq_set_notify_resume(struct task_struct *t) | 1863 | static inline void rseq_set_notify_resume(struct task_struct *t) |
| 1865 | { | 1864 | { |
| 1866 | } | 1865 | } |
| 1867 | static inline void rseq_handle_notify_resume(struct pt_regs *regs) | 1866 | static inline void rseq_handle_notify_resume(struct ksignal *ksig, |
| 1867 | struct pt_regs *regs) | ||
| 1868 | { | 1868 | { |
| 1869 | } | 1869 | } |
| 1870 | static inline void rseq_signal_deliver(struct pt_regs *regs) | 1870 | static inline void rseq_signal_deliver(struct ksignal *ksig, |
| 1871 | struct pt_regs *regs) | ||
| 1871 | { | 1872 | { |
| 1872 | } | 1873 | } |
| 1873 | static inline void rseq_preempt(struct task_struct *t) | 1874 | static inline void rseq_preempt(struct task_struct *t) |
diff --git a/kernel/rseq.c b/kernel/rseq.c index ae306f90c514..22b6acf1ad63 100644 --- a/kernel/rseq.c +++ b/kernel/rseq.c | |||
| @@ -251,10 +251,10 @@ static int rseq_ip_fixup(struct pt_regs *regs) | |||
| 251 | * respect to other threads scheduled on the same CPU, and with respect | 251 | * respect to other threads scheduled on the same CPU, and with respect |
| 252 | * to signal handlers. | 252 | * to signal handlers. |
| 253 | */ | 253 | */ |
| 254 | void __rseq_handle_notify_resume(struct pt_regs *regs) | 254 | void __rseq_handle_notify_resume(struct ksignal *ksig, struct pt_regs *regs) |
| 255 | { | 255 | { |
| 256 | struct task_struct *t = current; | 256 | struct task_struct *t = current; |
| 257 | int ret; | 257 | int ret, sig; |
| 258 | 258 | ||
| 259 | if (unlikely(t->flags & PF_EXITING)) | 259 | if (unlikely(t->flags & PF_EXITING)) |
| 260 | return; | 260 | return; |
| @@ -268,7 +268,8 @@ void __rseq_handle_notify_resume(struct pt_regs *regs) | |||
| 268 | return; | 268 | return; |
| 269 | 269 | ||
| 270 | error: | 270 | error: |
| 271 | force_sig(SIGSEGV, t); | 271 | sig = ksig ? ksig->sig : 0; |
| 272 | force_sigsegv(sig, t); | ||
| 272 | } | 273 | } |
| 273 | 274 | ||
| 274 | #ifdef CONFIG_DEBUG_RSEQ | 275 | #ifdef CONFIG_DEBUG_RSEQ |
diff --git a/tools/testing/selftests/rseq/rseq-arm.h b/tools/testing/selftests/rseq/rseq-arm.h index 3b055f9aeaab..3cea19877227 100644 --- a/tools/testing/selftests/rseq/rseq-arm.h +++ b/tools/testing/selftests/rseq/rseq-arm.h | |||
| @@ -57,6 +57,7 @@ do { \ | |||
| 57 | #define __RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, \ | 57 | #define __RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, \ |
| 58 | abort_label, version, flags, \ | 58 | abort_label, version, flags, \ |
| 59 | start_ip, post_commit_offset, abort_ip) \ | 59 | start_ip, post_commit_offset, abort_ip) \ |
| 60 | ".balign 32\n\t" \ | ||
| 60 | __rseq_str(table_label) ":\n\t" \ | 61 | __rseq_str(table_label) ":\n\t" \ |
| 61 | ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ | 62 | ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \ |
| 62 | ".word " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \ | 63 | ".word " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \ |
diff --git a/tools/testing/selftests/rseq/run_param_test.sh b/tools/testing/selftests/rseq/run_param_test.sh index 3acd6d75ff9f..3acd6d75ff9f 100644..100755 --- a/tools/testing/selftests/rseq/run_param_test.sh +++ b/tools/testing/selftests/rseq/run_param_test.sh | |||
