X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fparisc%2Fkernel%2Fptrace.c;h=3f28de974556c838894ab5d12f40227d2c39c23e;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=871d7857fa9664e02ffe5c7ee38ec8ee33f7205b;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 871d7857f..3f28de974 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -17,12 +17,13 @@ #include #include #include +#include #include #include #include #include -#include +#include /* PSW bits we allow the debugger to modify */ #define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB) @@ -30,9 +31,9 @@ #undef DEBUG_PTRACE #ifdef DEBUG_PTRACE -#define DBG(x) printk x +#define DBG(x...) printk(x) #else -#define DBG(x) +#define DBG(x...) #endif #ifdef __LP64__ @@ -77,62 +78,20 @@ void ptrace_disable(struct task_struct *child) pa_psw(child)->l = 0; } -long sys_ptrace(long request, pid_t pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; long ret; #ifdef DEBUG_PTRACE long oaddr=addr, odata=data; #endif - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT)) - goto out_tsk; - - ret = -EPERM; - if (pid == 1) /* no messing around with init! */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { int copied; #ifdef __LP64__ - if (is_compat_task(child)) { + if (__is_compat_task(child)) { unsigned int tmp; addr &= 0xffffffffL; @@ -141,9 +100,9 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) if (copied != sizeof(tmp)) goto out_tsk; ret = put_user(tmp,(unsigned int *) data); - DBG(("sys_ptrace(PEEK%s, %d, %lx, %lx) returning %ld, data %x\n", + DBG("sys_ptrace(PEEK%s, %d, %lx, %lx) returning %ld, data %x\n", request == PTRACE_PEEKTEXT ? "TEXT" : "DATA", - pid, oaddr, odata, ret, tmp)); + pid, oaddr, odata, ret, tmp); } else #endif @@ -164,11 +123,11 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) case PTRACE_POKEDATA: ret = 0; #ifdef __LP64__ - if (is_compat_task(child)) { + if (__is_compat_task(child)) { unsigned int tmp = (unsigned int)data; - DBG(("sys_ptrace(POKE%s, %d, %lx, %lx)\n", + DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n", request == PTRACE_POKETEXT ? "TEXT" : "DATA", - pid, oaddr, odata)); + pid, oaddr, odata); addr &= 0xffffffffL; if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1) == sizeof(tmp)) goto out_tsk; @@ -187,7 +146,7 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) case PTRACE_PEEKUSR: { ret = -EIO; #ifdef __LP64__ - if (is_compat_task(child)) { + if (__is_compat_task(child)) { unsigned int tmp; if (addr & (sizeof(int)-1)) @@ -197,8 +156,8 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) tmp = *(unsigned int *) ((char *) task_regs(child) + addr); ret = put_user(tmp, (unsigned int *) data); - DBG(("sys_ptrace(PEEKUSR, %d, %lx, %lx) returning %ld, addr %lx, data %x\n", - pid, oaddr, odata, ret, addr, tmp)); + DBG("sys_ptrace(PEEKUSR, %d, %lx, %lx) returning %ld, addr %lx, data %x\n", + pid, oaddr, odata, ret, addr, tmp); } else #endif @@ -237,8 +196,8 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) * BEWARE, if you set N, and then single step, it won't * stop on the nullified instruction. */ - DBG(("sys_ptrace(POKEUSR, %d, %lx, %lx)\n", - pid, oaddr, odata)); + DBG("sys_ptrace(POKEUSR, %d, %lx, %lx)\n", + pid, oaddr, odata); data &= USER_PSW_BITS; task_regs(child)->gr[0] &= ~USER_PSW_BITS; task_regs(child)->gr[0] |= data; @@ -246,14 +205,14 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) goto out_tsk; } #ifdef __LP64__ - if (is_compat_task(child)) { + if (__is_compat_task(child)) { if (addr & (sizeof(int)-1)) goto out_tsk; if ((addr = translate_usr_offset(addr)) < 0) goto out_tsk; - DBG(("sys_ptrace(POKEUSR, %d, %lx, %lx) addr %lx\n", - pid, oaddr, odata, addr)); - if (addr >= PT_FR0 && addr <= PT_FR31) { + DBG("sys_ptrace(POKEUSR, %d, %lx, %lx) addr %lx\n", + pid, oaddr, odata, addr); + if (addr >= PT_FR0 && addr <= PT_FR31 + 4) { /* Special case, fp regs are 64 bits anyway */ *(unsigned int *) ((char *) task_regs(child) + addr) = data; ret = 0; @@ -275,7 +234,7 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) goto out_tsk; if ((addr >= PT_GR1 && addr <= PT_GR31) || addr == PT_IAOQ0 || addr == PT_IAOQ1 || - (addr >= PT_FR0 && addr <= PT_FR31) || + (addr >= PT_FR0 && addr <= PT_FR31 + 4) || addr == PT_SAR) { *(unsigned long *) ((char *) task_regs(child) + addr) = data; ret = 0; @@ -286,9 +245,9 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: ret = -EIO; - DBG(("sys_ptrace(%s)\n", - request == PTRACE_SYSCALL ? "SYSCALL" : "CONT")); - if ((unsigned long) data > _NSIG) + DBG("sys_ptrace(%s)\n", + request == PTRACE_SYSCALL ? "SYSCALL" : "CONT"); + if (!valid_signal(data)) goto out_tsk; child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP); if (request == PTRACE_SYSCALL) { @@ -305,16 +264,17 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) * sigkill. perhaps it should be put in the status * that it wants to exit. */ - DBG(("sys_ptrace(KILL)\n")); - if (child->state == TASK_ZOMBIE) /* already dead */ + ret = 0; + DBG("sys_ptrace(KILL)\n"); + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ goto out_tsk; child->exit_code = SIGKILL; goto out_wake_notrap; case PTRACE_SINGLEBLOCK: - DBG(("sys_ptrace(SINGLEBLOCK)\n")); + DBG("sys_ptrace(SINGLEBLOCK)\n"); ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) goto out_tsk; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->ptrace &= ~PT_SINGLESTEP; @@ -329,10 +289,11 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) goto out_wake; case PTRACE_SINGLESTEP: - DBG(("sys_ptrace(SINGLESTEP)\n")); + DBG("sys_ptrace(SINGLESTEP)\n"); ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) goto out_tsk; + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->ptrace &= ~PT_BLOCKSTEP; child->ptrace |= PT_SINGLESTEP; @@ -354,7 +315,7 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) /* Don't wake up the child, but let the parent know something happened. */ si.si_code = TRAP_TRACE; - si.si_addr = (void *) (task_regs(child)->iaoq[0] & ~3); + si.si_addr = (void __user *) (task_regs(child)->iaoq[0] & ~3); si.si_signo = SIGTRAP; si.si_errno = 0; force_sig_info(SIGTRAP, &si, child); @@ -382,6 +343,10 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) ret = ptrace_detach(child, data); goto out_tsk; + case PTRACE_GETEVENTMSG: + ret = put_user(child->ptrace_message, (unsigned int __user *) data); + goto out_tsk; + default: ret = ptrace_request(child, request, addr, data); goto out_tsk; @@ -393,11 +358,8 @@ out_wake: wake_up_process(child); ret = 0; out_tsk: - put_task_struct(child); -out: - unlock_kernel(); - DBG(("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n", - request, pid, oaddr, odata, ret)); + DBG("arch_ptrace(%ld, %d, %lx, %lx) returning %ld\n", + request, pid, oaddr, odata, ret); return ret; }