aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2008-07-30 06:55:30 -0400
committerPaul Mundt <lethal@linux-sh.org>2008-08-01 15:39:33 -0400
commitab99c733ae73cce31f2a2434f7099564e5a73d95 (patch)
treec9eb381f05688b8b4e79d2ffe495b4d4b302f2d4 /arch
parentc459dbf294b4a3d70490a468a7ca3907fb2c2f57 (diff)
sh: Make syscall tracer use tracehook notifiers, add TIF_NOTIFY_RESUME.
This follows the changes in commits: 7d6d637dac2050f30a1b57b0a3dc5de4a10616ba 4f72c4279eab1e5f3ed1ac4e55d4527617582392 on powerpc. Adding in TIF_NOTIFY_RESUME, and cleaning up the syscall tracing to be more generic. This is an incremental step to turning on tracehook, as well as unifying more of the ptrace and signal code across the 32/64 split. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/sh/include/asm/thread_info.h11
-rw-r--r--arch/sh/kernel/cpu/sh5/entry.S17
-rw-r--r--arch/sh/kernel/entry-common.S12
-rw-r--r--arch/sh/kernel/ptrace_32.c54
-rw-r--r--arch/sh/kernel/ptrace_64.c50
-rw-r--r--arch/sh/kernel/signal_32.c22
-rw-r--r--arch/sh/kernel/signal_64.c166
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 03d1e386670c..0a894cafb1dd 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 bba331d5ef74..04c7da968146 100644
--- a/arch/sh/kernel/cpu/sh5/entry.S
+++ b/arch/sh/kernel/cpu/sh5/entry.S
@@ -987,11 +987,11 @@ work_resched:
987work_notifysig: 987work_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
996restore_all: 996restore_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 a34417c8ee0a..0bc17def55a7 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
224syscall_trace_entry: 222syscall_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
3902: .long NR_syscalls 3872: .long NR_syscalls
3913: .long sys_call_table 3883: .long sys_call_table
3924: .long do_syscall_trace
393#ifdef CONFIG_TRACE_IRQFLAGS 389#ifdef CONFIG_TRACE_IRQFLAGS
3945: .long trace_hardirqs_on 3905: .long trace_hardirqs_on
3956: .long trace_hardirqs_off 3916: .long trace_hardirqs_off
396#endif 392#endif
3937: .long do_syscall_trace_enter
3948: .long do_syscall_trace_leave
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index ff66f97c564d..f48769b23bd6 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
219asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) 220asmlinkage 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
250out: 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
243asmlinkage 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 108f3962e39a..236d8bef9ccd 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
224asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit) 225asmlinkage 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
253out: 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
248asmlinkage 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 4bbbde895a53..51689d29ad45 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: 600no_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
620asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0, 623asmlinkage 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 552eb810cd85..1d62dfef77f1 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
45asmlinkage 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 */
55static 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 = &current->saved_sigmask;
75 else if (!oldset)
76 oldset = &current->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
96no_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, &current->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(&current->sighand->siglock); 750 spin_unlock_irq(&current->sighand->siglock);
674} 751}
675 752
676/* 753asmlinkage 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 */
685int 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 = &current->saved_sigmask;
705 else if (!oldset)
706 oldset = &current->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
725no_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, &current->saved_sigmask, NULL);
749 }
750
751 return 0;
752} 762}