Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / arch / arm26 / kernel / ptrace.c
index 57b9fb1..282e24d 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/signal.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
  */
 #define BREAKINST_ARM  0xef9f0001
 
-/*
- * Get the address of the live pt_regs for the specified task.
- * These are saved onto the top kernel stack when the process
- * is not running.
- *
- * Note: if a user thread is execve'd from kernel space, the
- * kernel stack will not be empty on entry to the kernel, so
- * ptracing these tasks will fail.
- */
-static inline struct pt_regs *
-get_user_regs(struct task_struct *task)
-{
-       return __get_user_regs(task->thread_info);
-}
-
 /*
  * this routine will get a word off of the processes privileged stack.
  * the offset is how far from the base addr as stored in the THREAD.
@@ -61,7 +47,7 @@ get_user_regs(struct task_struct *task)
  */
 static inline long get_user_reg(struct task_struct *task, int offset)
 {
-       return get_user_regs(task)->uregs[offset];
+       return task_pt_regs(task)->uregs[offset];
 }
 
 /*
@@ -73,7 +59,7 @@ static inline long get_user_reg(struct task_struct *task, int offset)
 static inline int
 put_user_reg(struct task_struct *task, int offset, long data)
 {
-       struct pt_regs newregs, *regs = get_user_regs(task);
+       struct pt_regs newregs, *regs = task_pt_regs(task);
        int ret = -EINVAL;
 
        newregs = *regs;
@@ -376,7 +362,7 @@ void ptrace_set_bpt(struct task_struct *child)
        u32 insn;
        int res;
 
-       regs = get_user_regs(child);
+       regs = task_pt_regs(child);
        pc = instruction_pointer(regs);
 
        res = read_instr(child, pc, &insn);
@@ -499,7 +485,7 @@ static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
  */
 static int ptrace_getregs(struct task_struct *tsk, void *uregs)
 {
-       struct pt_regs *regs = get_user_regs(tsk);
+       struct pt_regs *regs = task_pt_regs(tsk);
 
        return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
 }
@@ -514,7 +500,7 @@ static int ptrace_setregs(struct task_struct *tsk, void *uregs)
 
        ret = -EFAULT;
        if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
-               struct pt_regs *regs = get_user_regs(tsk);
+               struct pt_regs *regs = task_pt_regs(tsk);
 
                ret = -EINVAL;
                if (valid_user_regs(&newregs)) {
@@ -531,7 +517,7 @@ static int ptrace_setregs(struct task_struct *tsk, void *uregs)
  */
 static int ptrace_getfpregs(struct task_struct *tsk, void *ufp)
 {
-       return copy_to_user(ufp, &tsk->thread_info->fpstate,
+       return copy_to_user(ufp, &task_thread_info(tsk)->fpstate,
                            sizeof(struct user_fp)) ? -EFAULT : 0;
 }
 
@@ -540,12 +526,12 @@ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp)
  */
 static int ptrace_setfpregs(struct task_struct *tsk, void *ufp)
 {
-       tsk->used_math = 1;
-       return copy_from_user(&tsk->thread_info->fpstate, ufp,
+       set_stopped_child_used_math(tsk);
+       return copy_from_user(&task_thread_info(tsk)->fpstate, ufp,
                              sizeof(struct user_fp)) ? -EFAULT : 0;
 }
 
-static int do_ptrace(int request, struct task_struct *child, long addr, long data)
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
        unsigned long tmp;
        int ret;
@@ -591,7 +577,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
                case PTRACE_SYSCALL:
                case PTRACE_CONT:
                        ret = -EIO;
-                       if ((unsigned long) data > _NSIG)
+                       if (!valid_signal(data))
                                break;
                        if (request == PTRACE_SYSCALL)
                                set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -614,7 +600,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
                        /* make sure single-step breakpoint is gone. */
                        child->ptrace &= ~PT_SINGLESTEP;
                        ptrace_cancel_bpt(child);
-                       if (child->state != TASK_ZOMBIE) {
+                       if (child->exit_state != EXIT_ZOMBIE) {
                                child->exit_code = SIGKILL;
                                wake_up_process(child);
                        }
@@ -626,7 +612,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
                 */
                case PTRACE_SINGLESTEP:
                        ret = -EIO;
-                       if ((unsigned long) data > _NSIG)
+                       if (!valid_signal(data))
                                break;
                        child->ptrace |= PT_SINGLESTEP;
                        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
@@ -664,53 +650,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
        return ret;
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
-{
-       struct task_struct *child;
-       int ret;
-
-       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;
-
-       ret = -EPERM;
-       if (pid == 1)           /* you may not mess 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)
-               ret = do_ptrace(request, child, addr, data);
-
-out_tsk:
-       put_task_struct(child);
-out:
-       unlock_kernel();
-       return ret;
-}
-
 asmlinkage void syscall_trace(int why, struct pt_regs *regs)
 {
        unsigned long ip;
@@ -729,11 +668,8 @@ asmlinkage void syscall_trace(int why, struct pt_regs *regs)
 
        /* the 0x80 provides a way for the tracing parent to distinguish
           between a syscall stop and SIGTRAP delivery */
-       current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-                                       ? 0x80 : 0);
-       current->state = TASK_STOPPED;
-       notify_parent(current, SIGCHLD);
-       schedule();
+       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+                                ? 0x80 : 0));
        /*
         * 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