From: Prasanna Meda <pmeda@akamai.com>

Since Roland changed now to wakeup tracee with kill, I guess this needs to be fixed.
http://linus.bkbits.net:8080/linux-2.5/gnupatch@41e3fe5fIRH-W3aDnXZgfQ-qIvuXYg

ptrace_setsiginfo/ptrace_getsiginfo need to do locked access to
last_siginfo.  ptrace_notify()/ptrace_stop() sets the current->last_siginfo
and sleeps on schedule().  It can be waked up by kill signal from
signal_wake_up before debugger wakes it up.  On return from schedule(), the
current->last_siginfo is reset.

Signed-off-by: Prasanna Meda <pmeda@akamai.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/kernel/ptrace.c |   29 ++++++++++++++++++++++-------
 1 files changed, 22 insertions(+), 7 deletions(-)

diff -puN kernel/ptrace.c~ptrace-unlocked-access-to-last_siginfo-resending kernel/ptrace.c
--- 25/kernel/ptrace.c~ptrace-unlocked-access-to-last_siginfo-resending	Wed Jan 12 15:33:41 2005
+++ 25-akpm/kernel/ptrace.c	Wed Jan 12 15:33:41 2005
@@ -319,18 +319,33 @@ static int ptrace_setoptions(struct task
 
 static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
 {
-	if (child->last_siginfo == NULL)
-		return -EINVAL;
-	return copy_siginfo_to_user(data, child->last_siginfo);
+	siginfo_t lastinfo;
+
+	spin_lock_irq(&child->sighand->siglock);
+	if (likely(child->last_siginfo != NULL)) {
+		memcpy(&lastinfo, child->last_siginfo, sizeof (siginfo_t));
+		spin_unlock_irq(&child->sighand->siglock);
+		return copy_siginfo_to_user(data, &lastinfo);
+	}
+	spin_unlock_irq(&child->sighand->siglock);
+	return -EINVAL;
 }
 
 static int ptrace_setsiginfo(struct task_struct *child, siginfo_t __user * data)
 {
-	if (child->last_siginfo == NULL)
-		return -EINVAL;
-	if (copy_from_user(child->last_siginfo, data, sizeof (siginfo_t)) != 0)
+	siginfo_t newinfo;
+
+	if (copy_from_user(&newinfo, data, sizeof (siginfo_t)) != 0)
 		return -EFAULT;
-	return 0;
+
+	spin_lock_irq(&child->sighand->siglock);
+	if (likely(child->last_siginfo != NULL)) {
+		memcpy(child->last_siginfo, &newinfo, sizeof (siginfo_t));
+		spin_unlock_irq(&child->sighand->siglock);
+		return 0;
+	}
+	spin_unlock_irq(&child->sighand->siglock);
+	return -EINVAL;
 }
 
 int ptrace_request(struct task_struct *child, long request,
_