diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-10-10 21:33:20 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-10-10 21:33:57 +0200 |
commit | 753c4dd6a2fa2af81f5d809d610d29f2d9dd9bc1 (patch) | |
tree | c6c1869a58357945e501b2eba3485ca154ee2f07 /arch/s390/kernel | |
parent | d86730bb9597b02bff59a3a5a01c0094d71a265f (diff) |
[S390] ptrace changes
* System call parameter and result access functions
* Add tracehook calls
* Split syscall_trace into two functions do_syscall_trace_enter and
do_syscall_trace_exit
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/entry.S | 50 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 42 | ||||
-rw-r--r-- | arch/s390/kernel/ptrace.c | 61 | ||||
-rw-r--r-- | arch/s390/kernel/signal.c | 13 |
4 files changed, 118 insertions, 48 deletions
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 708cf9cf9a3..ed500ef799b 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -49,9 +49,9 @@ SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE -_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ +_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) -_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ +_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ _TIF_MCCK_PENDING) STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER @@ -318,6 +318,8 @@ sysc_work: bo BASED(sysc_reschedule) tm __TI_flags+3(%r9),_TIF_SIGPENDING bnz BASED(sysc_sigpending) + tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME + bnz BASED(sysc_notify_resume) tm __TI_flags+3(%r9),_TIF_RESTART_SVC bo BASED(sysc_restart) tm __TI_flags+3(%r9),_TIF_SINGLE_STEP @@ -356,6 +358,16 @@ sysc_sigpending: b BASED(sysc_work_loop) # +# _TIF_NOTIFY_RESUME is set, call do_notify_resume +# +sysc_notify_resume: + la %r2,SP_PTREGS(%r15) # load pt_regs + l %r1,BASED(.Ldo_notify_resume) + la %r14,BASED(sysc_work_loop) + br %r1 # call do_notify_resume + + +# # _TIF_RESTART_SVC is set, set up registers and restart svc # sysc_restart: @@ -378,20 +390,21 @@ sysc_singlestep: br %r1 # branch to do_single_step # -# call trace before and after sys_call +# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before +# and after the system call # sysc_tracesys: - l %r1,BASED(.Ltrace) + l %r1,BASED(.Ltrace_entry) la %r2,SP_PTREGS(%r15) # load pt_regs la %r3,0 srl %r7,2 st %r7,SP_R2(%r15) basr %r14,%r1 - clc SP_R2(4,%r15),BASED(.Lnr_syscalls) + cl %r2,BASED(.Lnr_syscalls) bnl BASED(sysc_tracenogo) l %r8,BASED(.Lsysc_table) - l %r7,SP_R2(%r15) # strace might have changed the - sll %r7,2 # system call + lr %r7,%r2 + sll %r7,2 # *4 l %r8,0(%r7,%r8) sysc_tracego: lm %r3,%r6,SP_R3(%r15) @@ -401,9 +414,8 @@ sysc_tracego: sysc_tracenogo: tm __TI_flags+3(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) bz BASED(sysc_return) - l %r1,BASED(.Ltrace) + l %r1,BASED(.Ltrace_exit) la %r2,SP_PTREGS(%r15) # load pt_regs - la %r3,1 la %r14,BASED(sysc_return) br %r1 @@ -666,6 +678,8 @@ io_work_loop: bo BASED(io_reschedule) tm __TI_flags+3(%r9),_TIF_SIGPENDING bnz BASED(io_sigpending) + tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME + bnz BASED(io_notify_resume) b BASED(io_restore) io_work_done: @@ -704,6 +718,19 @@ io_sigpending: TRACE_IRQS_OFF b BASED(io_work_loop) +# +# _TIF_SIGPENDING is set, call do_signal +# +io_notify_resume: + TRACE_IRQS_ON + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts + la %r2,SP_PTREGS(%r15) # load pt_regs + l %r1,BASED(.Ldo_notify_resume) + basr %r14,%r1 # call do_signal + stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts + TRACE_IRQS_OFF + b BASED(io_work_loop) + /* * External interrupt handler routine */ @@ -1070,6 +1097,8 @@ cleanup_io_leave_insn: .Ldo_IRQ: .long do_IRQ .Ldo_extint: .long do_extint .Ldo_signal: .long do_signal +.Ldo_notify_resume: + .long do_notify_resume .Lhandle_per: .long do_single_step .Ldo_execve: .long do_execve .Lexecve_tail: .long execve_tail @@ -1079,7 +1108,8 @@ cleanup_io_leave_insn: .Lpreempt_schedule_irq: .long preempt_schedule_irq #endif -.Ltrace: .long syscall_trace +.Ltrace_entry: .long do_syscall_trace_enter +.Ltrace_exit: .long do_syscall_trace_exit .Lschedtail: .long schedule_tail .Lsysc_table: .long sys_call_table #ifdef CONFIG_TRACE_IRQFLAGS diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index fee10177dbf..d7ce150453f 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -52,9 +52,9 @@ SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER STACK_SIZE = 1 << STACK_SHIFT -_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ +_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) -_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ +_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ _TIF_MCCK_PENDING) #define BASED(name) name-system_call(%r13) @@ -310,6 +310,8 @@ sysc_work: jo sysc_reschedule tm __TI_flags+7(%r9),_TIF_SIGPENDING jnz sysc_sigpending + tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME + jnz sysc_notify_resume tm __TI_flags+7(%r9),_TIF_RESTART_SVC jo sysc_restart tm __TI_flags+7(%r9),_TIF_SINGLE_STEP @@ -345,6 +347,14 @@ sysc_sigpending: j sysc_work_loop # +# _TIF_NOTIFY_RESUME is set, call do_notify_resume +# +sysc_notify_resume: + la %r2,SP_PTREGS(%r15) # load pt_regs + larl %r14,sysc_work_loop + jg do_notify_resume # call do_notify_resume + +# # _TIF_RESTART_SVC is set, set up registers and restart svc # sysc_restart: @@ -367,20 +377,19 @@ sysc_singlestep: jg do_single_step # branch to do_sigtrap # -# call syscall_trace before and after system call -# special linkage: %r12 contains the return address for trace_svc +# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before +# and after the system call # sysc_tracesys: la %r2,SP_PTREGS(%r15) # load pt_regs la %r3,0 srl %r7,2 stg %r7,SP_R2(%r15) - brasl %r14,syscall_trace + brasl %r14,do_syscall_trace_enter lghi %r0,NR_syscalls - clg %r0,SP_R2(%r15) + clgr %r0,%r2 jnh sysc_tracenogo - lg %r7,SP_R2(%r15) # strace might have changed the - sll %r7,2 # system call + slag %r7,%r2,2 # *4 lgf %r8,0(%r7,%r10) sysc_tracego: lmg %r3,%r6,SP_R3(%r15) @@ -391,9 +400,8 @@ sysc_tracenogo: tm __TI_flags+7(%r9),(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT) jz sysc_return la %r2,SP_PTREGS(%r15) # load pt_regs - la %r3,1 larl %r14,sysc_return # return point is sysc_return - jg syscall_trace + jg do_syscall_trace_exit # # a new process exits the kernel with ret_from_fork @@ -672,6 +680,8 @@ io_work_loop: jo io_reschedule tm __TI_flags+7(%r9),_TIF_SIGPENDING jnz io_sigpending + tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME + jnz io_notify_resume j io_restore io_work_done: @@ -712,6 +722,18 @@ io_sigpending: TRACE_IRQS_OFF j io_work_loop +# +# _TIF_NOTIFY_RESUME or is set, call do_notify_resume +# +io_notify_resume: + TRACE_IRQS_ON + stosm __SF_EMPTY(%r15),0x03 # reenable interrupts + la %r2,SP_PTREGS(%r15) # load pt_regs + brasl %r14,do_notify_resume # call do_notify_resume + stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts + TRACE_IRQS_OFF + j io_work_loop + /* * External interrupt handler routine */ diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index c8b08289eb8..1f31be1ecc4 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -35,6 +35,7 @@ #include <linux/signal.h> #include <linux/elf.h> #include <linux/regset.h> +#include <linux/tracehook.h> #include <asm/segment.h> #include <asm/page.h> @@ -639,40 +640,44 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, } #endif -asmlinkage void -syscall_trace(struct pt_regs *regs, int entryexit) +asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) { - if (unlikely(current->audit_context) && entryexit) - audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]); - - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - goto out; - if (!(current->ptrace & PT_PTRACED)) - goto out; - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); + long ret; /* - * If the debuffer has set an invalid system call number, - * we prepare to skip the system call restart handling. + * The sysc_tracesys code in entry.S stored the system + * call number to gprs[2]. */ - if (!entryexit && regs->gprs[2] >= NR_syscalls) + ret = regs->gprs[2]; + if (test_thread_flag(TIF_SYSCALL_TRACE) && + (tracehook_report_syscall_entry(regs) || + regs->gprs[2] >= NR_syscalls)) { + /* + * Tracing decided this syscall should not happen or the + * debugger stored an invalid system call number. Skip + * the system call and the system call restart handling. + */ regs->trap = -1; - - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; + ret = -1; } - out: - if (unlikely(current->audit_context) && !entryexit) - audit_syscall_entry(test_thread_flag(TIF_31BIT)?AUDIT_ARCH_S390:AUDIT_ARCH_S390X, - regs->gprs[2], regs->orig_gpr2, regs->gprs[3], - regs->gprs[4], regs->gprs[5]); + + if (unlikely(current->audit_context)) + audit_syscall_entry(test_thread_flag(TIF_31BIT) ? + AUDIT_ARCH_S390 : AUDIT_ARCH_S390X, + regs->gprs[2], regs->orig_gpr2, + regs->gprs[3], regs->gprs[4], + regs->gprs[5]); + return ret; +} + +asmlinkage void do_syscall_trace_exit(struct pt_regs *regs) +{ + if (unlikely(current->audit_context)) + audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), + regs->gprs[2]); + + if (test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, 0); } /* diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index b9768204021..4f7fc3059a8 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -24,6 +24,7 @@ #include <linux/tty.h> #include <linux/personality.h> #include <linux/binfmts.h> +#include <linux/tracehook.h> #include <asm/ucontext.h> #include <asm/uaccess.h> #include <asm/lowcore.h> @@ -507,6 +508,12 @@ void do_signal(struct pt_regs *regs) */ if (current->thread.per_info.single_step) set_thread_flag(TIF_SINGLE_STEP); + + /* + * Let tracing know that we've done the handler setup. + */ + tracehook_signal_handler(signr, &info, &ka, regs, + test_thread_flag(TIF_SINGLE_STEP)); } return; } @@ -526,3 +533,9 @@ void do_signal(struct pt_regs *regs) set_thread_flag(TIF_RESTART_SVC); } } + +void do_notify_resume(struct pt_regs *regs) +{ + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); +} |