x86: use generic per-device dma coherent allocator
[pandora-kernel.git] / kernel / ptrace.c
index fdb34e8..6c19e94 100644 (file)
@@ -73,7 +73,7 @@ void __ptrace_unlink(struct task_struct *child)
        BUG_ON(!child->ptrace);
 
        child->ptrace = 0;
-       if (!list_empty(&child->ptrace_list)) {
+       if (ptrace_reparented(child)) {
                list_del_init(&child->ptrace_list);
                remove_parent(child);
                child->parent = child->real_parent;
@@ -168,8 +168,6 @@ int ptrace_attach(struct task_struct *task)
        audit_ptrace(task);
 
        retval = -EPERM;
-       if (task->pid <= 1)
-               goto out;
        if (same_thread_group(task, current))
                goto out;
 
@@ -208,8 +206,7 @@ repeat:
 
        __ptrace_link(task, current);
 
-       force_sig_specific(SIGSTOP, task);
-
+       send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
 bad:
        write_unlock_irqrestore(&tasklist_lock, flags);
        task_unlock(task);
@@ -323,9 +320,8 @@ static int ptrace_setoptions(struct task_struct *child, long data)
        return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
 }
 
-static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
+static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info)
 {
-       siginfo_t lastinfo;
        int error = -ESRCH;
 
        read_lock(&tasklist_lock);
@@ -333,31 +329,25 @@ static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
                error = -EINVAL;
                spin_lock_irq(&child->sighand->siglock);
                if (likely(child->last_siginfo != NULL)) {
-                       lastinfo = *child->last_siginfo;
+                       *info = *child->last_siginfo;
                        error = 0;
                }
                spin_unlock_irq(&child->sighand->siglock);
        }
        read_unlock(&tasklist_lock);
-       if (!error)
-               return copy_siginfo_to_user(data, &lastinfo);
        return error;
 }
 
-static int ptrace_setsiginfo(struct task_struct *child, siginfo_t __user * data)
+static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
 {
-       siginfo_t newinfo;
        int error = -ESRCH;
 
-       if (copy_from_user(&newinfo, data, sizeof (siginfo_t)))
-               return -EFAULT;
-
        read_lock(&tasklist_lock);
        if (likely(child->sighand != NULL)) {
                error = -EINVAL;
                spin_lock_irq(&child->sighand->siglock);
                if (likely(child->last_siginfo != NULL)) {
-                       *child->last_siginfo = newinfo;
+                       *child->last_siginfo = *info;
                        error = 0;
                }
                spin_unlock_irq(&child->sighand->siglock);
@@ -424,6 +414,7 @@ int ptrace_request(struct task_struct *child, long request,
                   long addr, long data)
 {
        int ret = -EIO;
+       siginfo_t siginfo;
 
        switch (request) {
        case PTRACE_PEEKTEXT:
@@ -442,12 +433,22 @@ int ptrace_request(struct task_struct *child, long request,
        case PTRACE_GETEVENTMSG:
                ret = put_user(child->ptrace_message, (unsigned long __user *) data);
                break;
+
        case PTRACE_GETSIGINFO:
-               ret = ptrace_getsiginfo(child, (siginfo_t __user *) data);
+               ret = ptrace_getsiginfo(child, &siginfo);
+               if (!ret)
+                       ret = copy_siginfo_to_user((siginfo_t __user *) data,
+                                                  &siginfo);
                break;
+
        case PTRACE_SETSIGINFO:
-               ret = ptrace_setsiginfo(child, (siginfo_t __user *) data);
+               if (copy_from_user(&siginfo, (siginfo_t __user *) data,
+                                  sizeof siginfo))
+                       ret = -EFAULT;
+               else
+                       ret = ptrace_setsiginfo(child, &siginfo);
                break;
+
        case PTRACE_DETACH:      /* detach a process that was attached. */
                ret = ptrace_detach(child, data);
                break;
@@ -518,12 +519,6 @@ struct task_struct *ptrace_get_task_struct(pid_t pid)
 {
        struct task_struct *child;
 
-       /*
-        * Tracing init is not allowed.
-        */
-       if (pid == 1)
-               return ERR_PTR(-EPERM);
-
        read_lock(&tasklist_lock);
        child = find_task_by_vpid(pid);
        if (child)
@@ -539,7 +534,6 @@ struct task_struct *ptrace_get_task_struct(pid_t pid)
 #define arch_ptrace_attach(child)      do { } while (0)
 #endif
 
-#ifndef __ARCH_SYS_PTRACE
 asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 {
        struct task_struct *child;
@@ -587,7 +581,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
        unlock_kernel();
        return ret;
 }
-#endif /* __ARCH_SYS_PTRACE */
 
 int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data)
 {
@@ -608,7 +601,7 @@ int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data)
        return (copied == sizeof(data)) ? 0 : -EIO;
 }
 
-#ifdef CONFIG_COMPAT
+#if defined CONFIG_COMPAT && defined __ARCH_WANT_COMPAT_SYS_PTRACE
 #include <linux/compat.h>
 
 int compat_ptrace_request(struct task_struct *child, compat_long_t request,
@@ -616,6 +609,7 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
 {
        compat_ulong_t __user *datap = compat_ptr(data);
        compat_ulong_t word;
+       siginfo_t siginfo;
        int ret;
 
        switch (request) {
@@ -638,6 +632,23 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
                ret = put_user((compat_ulong_t) child->ptrace_message, datap);
                break;
 
+       case PTRACE_GETSIGINFO:
+               ret = ptrace_getsiginfo(child, &siginfo);
+               if (!ret)
+                       ret = copy_siginfo_to_user32(
+                               (struct compat_siginfo __user *) datap,
+                               &siginfo);
+               break;
+
+       case PTRACE_SETSIGINFO:
+               memset(&siginfo, 0, sizeof siginfo);
+               if (copy_siginfo_from_user32(
+                           &siginfo, (struct compat_siginfo __user *) datap))
+                       ret = -EFAULT;
+               else
+                       ret = ptrace_setsiginfo(child, &siginfo);
+               break;
+
        default:
                ret = ptrace_request(child, request, addr, data);
        }
@@ -645,7 +656,6 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
        return ret;
 }
 
-#ifdef __ARCH_WANT_COMPAT_SYS_PTRACE
 asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
                                  compat_long_t addr, compat_long_t data)
 {
@@ -688,6 +698,4 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
        unlock_kernel();
        return ret;
 }
-#endif /* __ARCH_WANT_COMPAT_SYS_PTRACE */
-
-#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_COMPAT && __ARCH_WANT_COMPAT_SYS_PTRACE */