diff options
-rw-r--r-- | arch/sh/include/asm/thread_info.h | 11 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh5/entry.S | 17 | ||||
-rw-r--r-- | arch/sh/kernel/entry-common.S | 12 | ||||
-rw-r--r-- | arch/sh/kernel/ptrace_32.c | 54 | ||||
-rw-r--r-- | arch/sh/kernel/ptrace_64.c | 50 | ||||
-rw-r--r-- | arch/sh/kernel/signal_32.c | 22 | ||||
-rw-r--r-- | arch/sh/kernel/signal_64.c | 166 |
7 files changed, 174 insertions, 158 deletions
diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h index 03d1e386670..0a894cafb1d 100644 --- a/arch/sh/include/asm/thread_info.h +++ b/arch/sh/include/asm/thread_info.h | |||
@@ -119,10 +119,11 @@ static inline struct thread_info *current_thread_info(void) | |||
119 | #define TIF_SINGLESTEP 4 /* singlestepping active */ | 119 | #define TIF_SINGLESTEP 4 /* singlestepping active */ |
120 | #define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ | 120 | #define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ |
121 | #define TIF_SECCOMP 6 /* secure computing */ | 121 | #define TIF_SECCOMP 6 /* secure computing */ |
122 | #define TIF_NOTIFY_RESUME 7 /* callback before returning to user */ | ||
122 | #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ | 123 | #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ |
123 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ | 124 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ |
124 | #define TIF_MEMDIE 18 | 125 | #define TIF_MEMDIE 18 |
125 | #define TIF_FREEZE 19 | 126 | #define TIF_FREEZE 19 /* Freezing for suspend */ |
126 | 127 | ||
127 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) | 128 | #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) |
128 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) | 129 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) |
@@ -131,6 +132,7 @@ static inline struct thread_info *current_thread_info(void) | |||
131 | #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) | 132 | #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) |
132 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) | 133 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) |
133 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) | 134 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) |
135 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) | ||
134 | #define _TIF_USEDFPU (1 << TIF_USEDFPU) | 136 | #define _TIF_USEDFPU (1 << TIF_USEDFPU) |
135 | #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) | 137 | #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) |
136 | #define _TIF_FREEZE (1 << TIF_FREEZE) | 138 | #define _TIF_FREEZE (1 << TIF_FREEZE) |
@@ -146,9 +148,10 @@ static inline struct thread_info *current_thread_info(void) | |||
146 | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP) | 148 | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP) |
147 | 149 | ||
148 | /* work to do on any return to u-space */ | 150 | /* work to do on any return to u-space */ |
149 | #define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \ | 151 | #define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \ |
150 | _TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \ | 152 | _TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \ |
151 | _TIF_SINGLESTEP | _TIF_RESTORE_SIGMASK) | 153 | _TIF_SINGLESTEP | _TIF_RESTORE_SIGMASK | \ |
154 | _TIF_NOTIFY_RESUME) | ||
152 | 155 | ||
153 | /* work to do on interrupt/exception return */ | 156 | /* work to do on interrupt/exception return */ |
154 | #define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \ | 157 | #define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \ |
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index bba331d5ef7..04c7da96814 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S | |||
@@ -987,11 +987,11 @@ work_resched: | |||
987 | work_notifysig: | 987 | work_notifysig: |
988 | gettr tr1, LINK | 988 | gettr tr1, LINK |
989 | 989 | ||
990 | movi do_signal, r6 | 990 | movi do_notify_resume, r6 |
991 | ptabs r6, tr0 | 991 | ptabs r6, tr0 |
992 | or SP, ZERO, r2 | 992 | or SP, ZERO, r2 |
993 | or ZERO, ZERO, r3 | 993 | or r7, ZERO, r3 |
994 | blink tr0, LINK /* Call do_signal(regs, 0), return here */ | 994 | blink tr0, LINK /* Call do_notify_resume(regs, current_thread_info->flags), return here */ |
995 | 995 | ||
996 | restore_all: | 996 | restore_all: |
997 | /* Do prefetches */ | 997 | /* Do prefetches */ |
@@ -1305,13 +1305,15 @@ syscall_allowed: | |||
1305 | beq/l r6, ZERO, tr0 | 1305 | beq/l r6, ZERO, tr0 |
1306 | 1306 | ||
1307 | /* Trace it by calling syscall_trace before and after */ | 1307 | /* Trace it by calling syscall_trace before and after */ |
1308 | movi syscall_trace, r4 | 1308 | movi do_syscall_trace_enter, r4 |
1309 | or SP, ZERO, r2 | 1309 | or SP, ZERO, r2 |
1310 | or ZERO, ZERO, r3 | ||
1311 | ptabs r4, tr0 | 1310 | ptabs r4, tr0 |
1312 | blink tr0, LINK | 1311 | blink tr0, LINK |
1313 | 1312 | ||
1314 | /* Reload syscall number as r5 is trashed by syscall_trace */ | 1313 | /* Save the retval */ |
1314 | st.q SP, FRAME_R(2), r2 | ||
1315 | |||
1316 | /* Reload syscall number as r5 is trashed by do_syscall_trace_enter */ | ||
1315 | ld.q SP, FRAME_S(FSYSCALL_ID), r5 | 1317 | ld.q SP, FRAME_S(FSYSCALL_ID), r5 |
1316 | andi r5, 0x1ff, r5 | 1318 | andi r5, 0x1ff, r5 |
1317 | 1319 | ||
@@ -1343,9 +1345,8 @@ syscall_ret_trace: | |||
1343 | /* We get back here only if under trace */ | 1345 | /* We get back here only if under trace */ |
1344 | st.q SP, FRAME_R(9), r2 /* Save return value */ | 1346 | st.q SP, FRAME_R(9), r2 /* Save return value */ |
1345 | 1347 | ||
1346 | movi syscall_trace, LINK | 1348 | movi do_syscall_trace_leave, LINK |
1347 | or SP, ZERO, r2 | 1349 | or SP, ZERO, r2 |
1348 | movi 1, r3 | ||
1349 | ptabs LINK, tr0 | 1350 | ptabs LINK, tr0 |
1350 | blink tr0, LINK | 1351 | blink tr0, LINK |
1351 | 1352 | ||
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index a34417c8ee0..0bc17def55a 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S | |||
@@ -211,10 +211,8 @@ syscall_exit_work: | |||
211 | nop | 211 | nop |
212 | #endif | 212 | #endif |
213 | sti | 213 | sti |
214 | ! XXX setup arguments... | ||
215 | mov r15, r4 | 214 | mov r15, r4 |
216 | mov #1, r5 | 215 | mov.l 8f, r0 ! do_syscall_trace_leave |
217 | mov.l 4f, r0 ! do_syscall_trace | ||
218 | jsr @r0 | 216 | jsr @r0 |
219 | nop | 217 | nop |
220 | bra resume_userspace | 218 | bra resume_userspace |
@@ -223,12 +221,11 @@ syscall_exit_work: | |||
223 | .align 2 | 221 | .align 2 |
224 | syscall_trace_entry: | 222 | syscall_trace_entry: |
225 | ! Yes it is traced. | 223 | ! Yes it is traced. |
226 | ! XXX setup arguments... | ||
227 | mov r15, r4 | 224 | mov r15, r4 |
228 | mov #0, r5 | 225 | mov.l 7f, r11 ! Call do_syscall_trace_enter which notifies |
229 | mov.l 4f, r11 ! Call do_syscall_trace which notifies | ||
230 | jsr @r11 ! superior (will chomp R[0-7]) | 226 | jsr @r11 ! superior (will chomp R[0-7]) |
231 | nop | 227 | nop |
228 | mov.l r0, @(OFF_R0,r15) ! Save return value | ||
232 | ! Reload R0-R4 from kernel stack, where the | 229 | ! Reload R0-R4 from kernel stack, where the |
233 | ! parent may have modified them using | 230 | ! parent may have modified them using |
234 | ! ptrace(POKEUSR). (Note that R0-R2 are | 231 | ! ptrace(POKEUSR). (Note that R0-R2 are |
@@ -389,8 +386,9 @@ syscall_exit: | |||
389 | #endif | 386 | #endif |
390 | 2: .long NR_syscalls | 387 | 2: .long NR_syscalls |
391 | 3: .long sys_call_table | 388 | 3: .long sys_call_table |
392 | 4: .long do_syscall_trace | ||
393 | #ifdef CONFIG_TRACE_IRQFLAGS | 389 | #ifdef CONFIG_TRACE_IRQFLAGS |
394 | 5: .long trace_hardirqs_on | 390 | 5: .long trace_hardirqs_on |
395 | 6: .long trace_hardirqs_off | 391 | 6: .long trace_hardirqs_off |
396 | #endif | 392 | #endif |
393 | 7: .long do_syscall_trace_enter | ||
394 | 8: .long do_syscall_trace_leave | ||
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index ff66f97c564..f48769b23bd 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/audit.h> | 22 | #include <linux/audit.h> |
23 | #include <linux/seccomp.h> | 23 | #include <linux/seccomp.h> |
24 | #include <linux/tracehook.h> | ||
24 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
25 | #include <asm/pgtable.h> | 26 | #include <asm/pgtable.h> |
26 | #include <asm/system.h> | 27 | #include <asm/system.h> |
@@ -216,41 +217,38 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
216 | return ret; | 217 | return ret; |
217 | } | 218 | } |
218 | 219 | ||
219 | asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) | 220 | asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) |
220 | { | 221 | { |
221 | struct task_struct *tsk = current; | 222 | long ret = 0; |
222 | 223 | ||
223 | secure_computing(regs->regs[0]); | 224 | secure_computing(regs->regs[0]); |
224 | 225 | ||
225 | if (unlikely(current->audit_context) && entryexit) | 226 | if (test_thread_flag(TIF_SYSCALL_TRACE) && |
226 | audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]), | 227 | tracehook_report_syscall_entry(regs)) |
227 | regs->regs[0]); | 228 | /* |
228 | 229 | * Tracing decided this syscall should not happen. | |
229 | if (!test_thread_flag(TIF_SYSCALL_TRACE) && | 230 | * We'll return a bogus call number to get an ENOSYS |
230 | !test_thread_flag(TIF_SINGLESTEP)) | 231 | * error, but leave the original number in regs->regs[0]. |
231 | goto out; | 232 | */ |
232 | if (!(tsk->ptrace & PT_PTRACED)) | 233 | ret = -1L; |
233 | goto out; | ||
234 | |||
235 | /* the 0x80 provides a way for the tracing parent to distinguish | ||
236 | between a syscall stop and SIGTRAP delivery */ | ||
237 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) && | ||
238 | !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0)); | ||
239 | |||
240 | /* | ||
241 | * this isn't the same as continuing with a signal, but it will do | ||
242 | * for normal use. strace only continues with a signal if the | ||
243 | * stopping signal is not SIGTRAP. -brl | ||
244 | */ | ||
245 | if (tsk->exit_code) { | ||
246 | send_sig(tsk->exit_code, tsk, 1); | ||
247 | tsk->exit_code = 0; | ||
248 | } | ||
249 | 234 | ||
250 | out: | 235 | if (unlikely(current->audit_context)) |
251 | if (unlikely(current->audit_context) && !entryexit) | ||
252 | audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[3], | 236 | audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[3], |
253 | regs->regs[4], regs->regs[5], | 237 | regs->regs[4], regs->regs[5], |
254 | regs->regs[6], regs->regs[7]); | 238 | regs->regs[6], regs->regs[7]); |
255 | 239 | ||
240 | return ret ?: regs->regs[0]; | ||
241 | } | ||
242 | |||
243 | asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) | ||
244 | { | ||
245 | int step; | ||
246 | |||
247 | if (unlikely(current->audit_context)) | ||
248 | audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]), | ||
249 | regs->regs[0]); | ||
250 | |||
251 | step = test_thread_flag(TIF_SINGLESTEP); | ||
252 | if (step || test_thread_flag(TIF_SYSCALL_TRACE)) | ||
253 | tracehook_report_syscall_exit(regs, step); | ||
256 | } | 254 | } |
diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index 108f3962e39..236d8bef9cc 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/syscalls.h> | 28 | #include <linux/syscalls.h> |
29 | #include <linux/audit.h> | 29 | #include <linux/audit.h> |
30 | #include <linux/seccomp.h> | 30 | #include <linux/seccomp.h> |
31 | #include <linux/tracehook.h> | ||
31 | #include <asm/io.h> | 32 | #include <asm/io.h> |
32 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
33 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
@@ -221,40 +222,37 @@ asmlinkage int sh64_ptrace(long request, long pid, long addr, long data) | |||
221 | return sys_ptrace(request, pid, addr, data); | 222 | return sys_ptrace(request, pid, addr, data); |
222 | } | 223 | } |
223 | 224 | ||
224 | asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit) | 225 | asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs) |
225 | { | 226 | { |
226 | struct task_struct *tsk = current; | 227 | long long ret = 0; |
227 | 228 | ||
228 | secure_computing(regs->regs[9]); | 229 | secure_computing(regs->regs[9]); |
229 | 230 | ||
230 | if (unlikely(current->audit_context) && entryexit) | 231 | if (test_thread_flag(TIF_SYSCALL_TRACE) && |
231 | audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]), | 232 | tracehook_report_syscall_entry(regs)) |
232 | regs->regs[9]); | 233 | /* |
233 | 234 | * Tracing decided this syscall should not happen. | |
234 | if (!test_thread_flag(TIF_SYSCALL_TRACE) && | 235 | * We'll return a bogus call number to get an ENOSYS |
235 | !test_thread_flag(TIF_SINGLESTEP)) | 236 | * error, but leave the original number in regs->regs[0]. |
236 | goto out; | 237 | */ |
237 | if (!(tsk->ptrace & PT_PTRACED)) | 238 | ret = -1LL; |
238 | goto out; | ||
239 | |||
240 | ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) && | ||
241 | !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0)); | ||
242 | |||
243 | /* | ||
244 | * this isn't the same as continuing with a signal, but it will do | ||
245 | * for normal use. strace only continues with a signal if the | ||
246 | * stopping signal is not SIGTRAP. -brl | ||
247 | */ | ||
248 | if (tsk->exit_code) { | ||
249 | send_sig(tsk->exit_code, tsk, 1); | ||
250 | tsk->exit_code = 0; | ||
251 | } | ||
252 | 239 | ||
253 | out: | 240 | if (unlikely(current->audit_context)) |
254 | if (unlikely(current->audit_context) && !entryexit) | ||
255 | audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[1], | 241 | audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[1], |
256 | regs->regs[2], regs->regs[3], | 242 | regs->regs[2], regs->regs[3], |
257 | regs->regs[4], regs->regs[5]); | 243 | regs->regs[4], regs->regs[5]); |
244 | |||
245 | return ret ?: regs->regs[9]; | ||
246 | } | ||
247 | |||
248 | asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) | ||
249 | { | ||
250 | if (unlikely(current->audit_context)) | ||
251 | audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]), | ||
252 | regs->regs[9]); | ||
253 | |||
254 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | ||
255 | tracehook_report_syscall_exit(regs, 0); | ||
258 | } | 256 | } |
259 | 257 | ||
260 | /* Called with interrupts disabled */ | 258 | /* Called with interrupts disabled */ |
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c index 4bbbde895a5..51689d29ad4 100644 --- a/arch/sh/kernel/signal_32.c +++ b/arch/sh/kernel/signal_32.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/binfmts.h> | 24 | #include <linux/binfmts.h> |
25 | #include <linux/freezer.h> | 25 | #include <linux/freezer.h> |
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/tracehook.h> | ||
27 | #include <asm/system.h> | 28 | #include <asm/system.h> |
28 | #include <asm/ucontext.h> | 29 | #include <asm/ucontext.h> |
29 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
@@ -507,14 +508,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | |||
507 | switch (regs->regs[0]) { | 508 | switch (regs->regs[0]) { |
508 | case -ERESTART_RESTARTBLOCK: | 509 | case -ERESTART_RESTARTBLOCK: |
509 | case -ERESTARTNOHAND: | 510 | case -ERESTARTNOHAND: |
511 | no_system_call_restart: | ||
510 | regs->regs[0] = -EINTR; | 512 | regs->regs[0] = -EINTR; |
511 | break; | 513 | break; |
512 | 514 | ||
513 | case -ERESTARTSYS: | 515 | case -ERESTARTSYS: |
514 | if (!(ka->sa.sa_flags & SA_RESTART)) { | 516 | if (!(ka->sa.sa_flags & SA_RESTART)) |
515 | regs->regs[0] = -EINTR; | 517 | goto no_system_call_restart; |
516 | break; | ||
517 | } | ||
518 | /* fallthrough */ | 518 | /* fallthrough */ |
519 | case -ERESTARTNOINTR: | 519 | case -ERESTARTNOINTR: |
520 | regs->regs[0] = save_r0; | 520 | regs->regs[0] = save_r0; |
@@ -589,12 +589,15 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) | |||
589 | * clear the TIF_RESTORE_SIGMASK flag */ | 589 | * clear the TIF_RESTORE_SIGMASK flag */ |
590 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 590 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
591 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 591 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
592 | |||
593 | tracehook_signal_handler(signr, &info, &ka, regs, | ||
594 | test_thread_flag(TIF_SINGLESTEP)); | ||
592 | } | 595 | } |
593 | 596 | ||
594 | return; | 597 | return; |
595 | } | 598 | } |
596 | 599 | ||
597 | no_signal: | 600 | no_signal: |
598 | /* Did we come from a system call? */ | 601 | /* Did we come from a system call? */ |
599 | if (regs->tra >= 0) { | 602 | if (regs->tra >= 0) { |
600 | /* Restart the system call - no handlers present */ | 603 | /* Restart the system call - no handlers present */ |
@@ -618,9 +621,14 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) | |||
618 | } | 621 | } |
619 | 622 | ||
620 | asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0, | 623 | asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0, |
621 | __u32 thread_info_flags) | 624 | unsigned long thread_info_flags) |
622 | { | 625 | { |
623 | /* deal with pending signal delivery */ | 626 | /* deal with pending signal delivery */ |
624 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) | 627 | if (thread_info_flags & _TIF_SIGPENDING) |
625 | do_signal(regs, save_r0); | 628 | do_signal(regs, save_r0); |
629 | |||
630 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | ||
631 | clear_thread_flag(TIF_NOTIFY_RESUME); | ||
632 | tracehook_notify_resume(regs); | ||
633 | } | ||
626 | } | 634 | } |
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index 552eb810cd8..1d62dfef77f 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/ptrace.h> | 22 | #include <linux/ptrace.h> |
23 | #include <linux/unistd.h> | 23 | #include <linux/unistd.h> |
24 | #include <linux/stddef.h> | 24 | #include <linux/stddef.h> |
25 | #include <linux/tracehook.h> | ||
25 | #include <asm/ucontext.h> | 26 | #include <asm/ucontext.h> |
26 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
27 | #include <asm/pgtable.h> | 28 | #include <asm/pgtable.h> |
@@ -42,7 +43,84 @@ | |||
42 | 43 | ||
43 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 44 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
44 | 45 | ||
45 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); | 46 | /* |
47 | * Note that 'init' is a special process: it doesn't get signals it doesn't | ||
48 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | ||
49 | * mistake. | ||
50 | * | ||
51 | * Note that we go through the signals twice: once to check the signals that | ||
52 | * the kernel can handle, and then we build all the user-level signal handling | ||
53 | * stack-frames in one go after that. | ||
54 | */ | ||
55 | static int do_signal(struct pt_regs *regs, sigset_t *oldset) | ||
56 | { | ||
57 | siginfo_t info; | ||
58 | int signr; | ||
59 | struct k_sigaction ka; | ||
60 | |||
61 | /* | ||
62 | * We want the common case to go fast, which | ||
63 | * is why we may in certain cases get here from | ||
64 | * kernel mode. Just return without doing anything | ||
65 | * if so. | ||
66 | */ | ||
67 | if (!user_mode(regs)) | ||
68 | return 1; | ||
69 | |||
70 | if (try_to_freeze()) | ||
71 | goto no_signal; | ||
72 | |||
73 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
74 | oldset = ¤t->saved_sigmask; | ||
75 | else if (!oldset) | ||
76 | oldset = ¤t->blocked; | ||
77 | |||
78 | signr = get_signal_to_deliver(&info, &ka, regs, 0); | ||
79 | |||
80 | if (signr > 0) { | ||
81 | /* Whee! Actually deliver the signal. */ | ||
82 | handle_signal(signr, &info, &ka, oldset, regs); | ||
83 | |||
84 | /* | ||
85 | * If a signal was successfully delivered, the saved sigmask | ||
86 | * is in its frame, and we can clear the TIF_RESTORE_SIGMASK | ||
87 | * flag. | ||
88 | */ | ||
89 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
90 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
91 | |||
92 | tracehook_signal_handler(signr, &info, &ka, regs, 0); | ||
93 | return 1; | ||
94 | } | ||
95 | |||
96 | no_signal: | ||
97 | /* Did we come from a system call? */ | ||
98 | if (regs->syscall_nr >= 0) { | ||
99 | /* Restart the system call - no handlers present */ | ||
100 | switch (regs->regs[REG_RET]) { | ||
101 | case -ERESTARTNOHAND: | ||
102 | case -ERESTARTSYS: | ||
103 | case -ERESTARTNOINTR: | ||
104 | /* Decode Syscall # */ | ||
105 | regs->regs[REG_RET] = regs->syscall_nr; | ||
106 | regs->pc -= 4; | ||
107 | break; | ||
108 | |||
109 | case -ERESTART_RESTARTBLOCK: | ||
110 | regs->regs[REG_RET] = __NR_restart_syscall; | ||
111 | regs->pc -= 4; | ||
112 | break; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | /* No signal to deliver -- put the saved sigmask back */ | ||
117 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
118 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
119 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
120 | } | ||
121 | |||
122 | return 0; | ||
123 | } | ||
46 | 124 | ||
47 | /* | 125 | /* |
48 | * Atomically swap in the new signal mask, and wait for a signal. | 126 | * Atomically swap in the new signal mask, and wait for a signal. |
@@ -643,14 +721,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
643 | switch (regs->regs[REG_RET]) { | 721 | switch (regs->regs[REG_RET]) { |
644 | case -ERESTART_RESTARTBLOCK: | 722 | case -ERESTART_RESTARTBLOCK: |
645 | case -ERESTARTNOHAND: | 723 | case -ERESTARTNOHAND: |
724 | no_system_call_restart: | ||
646 | regs->regs[REG_RET] = -EINTR; | 725 | regs->regs[REG_RET] = -EINTR; |
647 | break; | 726 | break; |
648 | 727 | ||
649 | case -ERESTARTSYS: | 728 | case -ERESTARTSYS: |
650 | if (!(ka->sa.sa_flags & SA_RESTART)) { | 729 | if (!(ka->sa.sa_flags & SA_RESTART)) |
651 | regs->regs[REG_RET] = -EINTR; | 730 | goto no_system_call_restart; |
652 | break; | ||
653 | } | ||
654 | /* fallthrough */ | 731 | /* fallthrough */ |
655 | case -ERESTARTNOINTR: | 732 | case -ERESTARTNOINTR: |
656 | /* Decode syscall # */ | 733 | /* Decode syscall # */ |
@@ -673,80 +750,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
673 | spin_unlock_irq(¤t->sighand->siglock); | 750 | spin_unlock_irq(¤t->sighand->siglock); |
674 | } | 751 | } |
675 | 752 | ||
676 | /* | 753 | asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) |
677 | * Note that 'init' is a special process: it doesn't get signals it doesn't | ||
678 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | ||
679 | * mistake. | ||
680 | * | ||
681 | * Note that we go through the signals twice: once to check the signals that | ||
682 | * the kernel can handle, and then we build all the user-level signal handling | ||
683 | * stack-frames in one go after that. | ||
684 | */ | ||
685 | int do_signal(struct pt_regs *regs, sigset_t *oldset) | ||
686 | { | 754 | { |
687 | siginfo_t info; | 755 | if (thread_info_flags & _TIF_SIGPENDING) |
688 | int signr; | 756 | do_signal(regs, 0); |
689 | struct k_sigaction ka; | ||
690 | |||
691 | /* | ||
692 | * We want the common case to go fast, which | ||
693 | * is why we may in certain cases get here from | ||
694 | * kernel mode. Just return without doing anything | ||
695 | * if so. | ||
696 | */ | ||
697 | if (!user_mode(regs)) | ||
698 | return 1; | ||
699 | |||
700 | if (try_to_freeze()) | ||
701 | goto no_signal; | ||
702 | |||
703 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
704 | oldset = ¤t->saved_sigmask; | ||
705 | else if (!oldset) | ||
706 | oldset = ¤t->blocked; | ||
707 | |||
708 | signr = get_signal_to_deliver(&info, &ka, regs, 0); | ||
709 | |||
710 | if (signr > 0) { | ||
711 | /* Whee! Actually deliver the signal. */ | ||
712 | handle_signal(signr, &info, &ka, oldset, regs); | ||
713 | 757 | ||
714 | /* | 758 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
715 | * If a signal was successfully delivered, the saved sigmask | 759 | clear_thread_flag(TIF_NOTIFY_RESUME); |
716 | * is in its frame, and we can clear the TIF_RESTORE_SIGMASK | 760 | tracehook_notify_resume(regs); |
717 | * flag. | ||
718 | */ | ||
719 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
720 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
721 | |||
722 | return 1; | ||
723 | } | 761 | } |
724 | |||
725 | no_signal: | ||
726 | /* Did we come from a system call? */ | ||
727 | if (regs->syscall_nr >= 0) { | ||
728 | /* Restart the system call - no handlers present */ | ||
729 | switch (regs->regs[REG_RET]) { | ||
730 | case -ERESTARTNOHAND: | ||
731 | case -ERESTARTSYS: | ||
732 | case -ERESTARTNOINTR: | ||
733 | /* Decode Syscall # */ | ||
734 | regs->regs[REG_RET] = regs->syscall_nr; | ||
735 | regs->pc -= 4; | ||
736 | break; | ||
737 | |||
738 | case -ERESTART_RESTARTBLOCK: | ||
739 | regs->regs[REG_RET] = __NR_restart_syscall; | ||
740 | regs->pc -= 4; | ||
741 | break; | ||
742 | } | ||
743 | } | ||
744 | |||
745 | /* No signal to deliver -- put the saved sigmask back */ | ||
746 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
747 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
748 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
749 | } | ||
750 | |||
751 | return 0; | ||
752 | } | 762 | } |