Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Advertisement

Kernel v2.6.26-rc1 /kernel/ptrace.c

Filename:/kernel/ptrace.c
Lines Added:39
Lines Deleted:31
Also changed in: (Previous) 2.6.25-git20  2.6.25-git19  2.6.25-git18  2.6.25-git17  2.6.25-git16  2.6.25-git15 
(Following) 2.6.26-rc2  2.6.26-rc3  2.6.26-rc4  2.6.26-rc5  2.6.26-rc6  2.6.26-rc7 

Location
[  2.6.26-rc1
  [  kernel
     o  ptrace.c

Patch

diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index fdb34e8..6c19e94 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -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 */


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.