<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">
From: Prasanna Meda &lt;pmeda@akamai.com&gt;

ptrace_setsiginfo/ptrace_getsiginfo need to do locked access to
last_siginfo.  ptrace_notify()/ptrace_stop() sets the current-&gt;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-&gt;last_siginfo is reset.

Signed-off-by: Prasanna Meda &lt;pmeda@akamai.com&gt;
Signed-off-by: Andrew Morton &lt;akpm@osdl.org&gt;
---

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

diff -puN kernel/ptrace.c~ptrace-locked-accesss-to-ptrace-last_siginfo kernel/ptrace.c
--- 25/kernel/ptrace.c~ptrace-locked-accesss-to-ptrace-last_siginfo	2004-11-21 15:52:10.490855832 -0800
+++ 25-akpm/kernel/ptrace.c	2004-11-21 15:52:10.494855224 -0800
@@ -319,18 +319,33 @@ static int ptrace_setoptions(struct task
 
 static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
 {
-	if (child-&gt;last_siginfo == NULL)
-		return -EINVAL;
-	return copy_siginfo_to_user(data, child-&gt;last_siginfo);
+	siginfo_t lastinfo;
+
+	spin_lock_irq(&amp;child-&gt;sighand-&gt;siglock);
+	if (likely(child-&gt;last_siginfo != NULL)) {
+		memcpy(&amp;lastinfo, child-&gt;last_siginfo, sizeof (siginfo_t));
+		spin_unlock_irq(&amp;child-&gt;sighand-&gt;siglock);
+		return copy_siginfo_to_user(data, &amp;lastinfo);
+	}
+	spin_unlock_irq(&amp;child-&gt;sighand-&gt;siglock);
+	return -EINVAL;
 }
 
 static int ptrace_setsiginfo(struct task_struct *child, siginfo_t __user * data)
 {
-	if (child-&gt;last_siginfo == NULL)
-		return -EINVAL;
-	if (copy_from_user(child-&gt;last_siginfo, data, sizeof (siginfo_t)) != 0)
+	siginfo_t newinfo;
+
+	if (copy_from_user(&amp;newinfo, data, sizeof (siginfo_t)) != 0)
 		return -EFAULT;
-	return 0;
+
+	spin_lock_irq(&amp;child-&gt;sighand-&gt;siglock);
+	if (likely(child-&gt;last_siginfo != NULL)) {
+		memcpy(child-&gt;last_siginfo, &amp;newinfo, sizeof (siginfo_t));
+		spin_unlock_irq(&amp;child-&gt;sighand-&gt;siglock);
+		return 0;
+	}
+	spin_unlock_irq(&amp;child-&gt;sighand-&gt;siglock);
+	return -EINVAL;
 }
 
 int ptrace_request(struct task_struct *child, long request,
_
</pre></body></html>