X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fcris%2Farch-v10%2Fkernel%2Fptrace.c;h=961c0d58ded4a52ca5313e0ef94e62f8d0adf126;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=3c7e0a51a28246ed8d81685ec31e81d04df7f940;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index 3c7e0a51a..961c0d58d 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include @@ -23,8 +25,37 @@ */ #define DCCR_MASK 0x0000001f /* XNZVC */ -extern inline long get_reg(struct task_struct *, unsigned int); -extern inline long put_reg(struct task_struct *, unsigned int, unsigned long); +/* + * Get contents of register REGNO in task TASK. + */ +inline long get_reg(struct task_struct *task, unsigned int regno) +{ + /* USP is a special case, it's not in the pt_regs struct but + * in the tasks thread struct + */ + + if (regno == PT_USP) + return task->thread.usp; + else if (regno < PT_MAX) + return ((unsigned long *)task_pt_regs(task))[regno]; + else + return 0; +} + +/* + * Write contents of register REGNO in task TASK. + */ +inline int put_reg(struct task_struct *task, unsigned int regno, + unsigned long data) +{ + if (regno == PT_USP) + task->thread.usp = data; + else if (regno < PT_MAX) + ((unsigned long *)task_pt_regs(task))[regno] = data; + else + return -1; + return 0; +} /* * Called by kernel/ptrace.c when detaching. @@ -45,49 +76,10 @@ ptrace_disable(struct task_struct *child) * (in user space) where the result of the ptrace call is written (instead of * being returned). */ -asmlinkage int -sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; - - lock_kernel(); - ret = -EPERM; - - if (request == PTRACE_TRACEME) { - if (current->ptrace & PT_PTRACED) - goto out; - - 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; - - ret = -EPERM; - - if (pid == 1) /* Leave the init process alone! */ - 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; + unsigned long __user *datap = (unsigned long __user *)data; switch (request) { /* Read word at location address. */ @@ -102,7 +94,7 @@ sys_ptrace(long request, long pid, long addr, long data) if (copied != sizeof(tmp)) break; - ret = put_user(tmp,(unsigned long *) data); + ret = put_user(tmp,datap); break; } @@ -115,7 +107,7 @@ sys_ptrace(long request, long pid, long addr, long data) break; tmp = get_reg(child, addr >> 2); - ret = put_user(tmp, (unsigned long *)data); + ret = put_user(tmp, datap); break; } @@ -154,7 +146,7 @@ sys_ptrace(long request, long pid, long addr, long data) case PTRACE_CONT: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) { @@ -176,7 +168,7 @@ sys_ptrace(long request, long pid, long addr, long data) case PTRACE_KILL: ret = 0; - if (child->state == TASK_ZOMBIE) + if (child->exit_state == EXIT_ZOMBIE) break; child->exit_code = SIGKILL; @@ -189,7 +181,7 @@ sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SINGLESTEP: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -210,18 +202,18 @@ sys_ptrace(long request, long pid, long addr, long data) int i; unsigned long tmp; + ret = 0; for (i = 0; i <= PT_MAX; i++) { tmp = get_reg(child, i); - if (put_user(tmp, (unsigned long *) data)) { + if (put_user(tmp, datap)) { ret = -EFAULT; - goto out_tsk; + break; } data += sizeof(long); } - ret = 0; break; } @@ -230,10 +222,11 @@ sys_ptrace(long request, long pid, long addr, long data) int i; unsigned long tmp; + ret = 0; for (i = 0; i <= PT_MAX; i++) { - if (get_user(tmp, (unsigned long *) data)) { + if (get_user(tmp, datap)) { ret = -EFAULT; - goto out_tsk; + break; } if (i == PT_DCCR) { @@ -245,7 +238,6 @@ sys_ptrace(long request, long pid, long addr, long data) data += sizeof(long); } - ret = 0; break; } @@ -253,10 +245,7 @@ sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; }