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 / cris / arch-v10 / kernel / ptrace.c
index 3c7e0a5..961c0d5 100644 (file)
@@ -10,6 +10,8 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/signal.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
  */
 #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;
 }