Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Oct 2002 17:11:16 +0200 (CEST)
From:      Mark Kettenis <kettenis@chello.nl>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/44011: [PATCH] PT_CONTINUE, PT_KILL and PT_DETACH are broken
Message-ID:  <200210131511.g9DFBGbm000741@elgar.kettenis.dyndns.org>

next in thread | raw e-mail | index | archive | help

>Number:         44011
>Category:       kern
>Synopsis:       [PATCH] PT_CONTINUE, PT_KILL and PT_DETACH are broken
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Oct 13 08:20:01 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Mark Kettenis
>Release:        FreeBSD 5.0-CURRENT i386
>Organization:
>Environment:
System: FreeBSD elgar.kettenis.dyndns.org 5.0-CURRENT FreeBSD 5.0-CURRENT #7: Sun Oct 13 15:15:46 CEST 2002 kettenis@elgar.kettenis.dyndns.org:/usr/obj/usr/src/sys/GENERIC i386

>Description:
There's a long standing bug that prevents the PT_CONTINUE, PT_KILL and
PT_DETACH ptrace(2) requests from functioning as advertised in the
manual page.  As described in kern/35175, the PT_DETACH request will,
under certain circumstances, pass an unwanted signal on to the traced
process upan detaching from it.  The PT_CONTINUE request will
sometimes fail if you make it pass a signal that has "properties" that
differ from the properties of the signal that origionally caused the
traced process to be stopped.  Since PT_KILL is nothing than
PT_CONTINUE with SIGKILL, it is broken too.  In the PT_KILL case, this
leads to an unkillable process.

>How-To-Repeat:
These problems manifest themselves in the GDB testsuite where several
test will fail:

   FAIL: gdb.base/attach.exp: (timeout) attach2
   FAIL: gdb.base/attach.exp: (timeout) after attach2, set should_exit
   FAIL: gdb.base/attach.exp: (timeout) after attach2, set tbreak postloop
   FAIL: gdb.base/attach.exp: (timeout) after attach2, reach tbreak postloop
   FAIL: gdb.base/attach.exp: (timeout) after attach2, exit
   FAIL: gdb.base/attach.exp: set source path

because PT_DETACH doesn't work as advertised, and

   FAIL: gdb.base/attach.exp: (timeout) after attach3, exit

because PT_KILL doesn't work.

>Fix:
These bugs are caused by code in issignal(), where the signal that's
being handled isn't cleared if the process is no longer traced
(i.e. for a PT_DETACH request), and where the "properties" of the
current signal aren't updated when the signal to be taken is changed
by the parent (i.e. for a PT_CONTINUE or PT_KILL request).

The attached patch solves these problems.  The first problem is fixed
by a variant of the patch by Peter Edwards in kern/35175.  The second
problem is fixed by moving the initialisation of 'prop' further down,
such that it is set based on the right signal.  This patch is against
version 1.196 of kern_sig.c.

This patch is also available as:

   http://members.chello.nl/~m.m.kettenis/FreeBSD/5-current/ptrace.patch.

Mark

--- /usr/src/sys/kern/kern_sig.c.orig	Wed Oct  2 11:08:11 2002
+++ /usr/src/sys/kern/kern_sig.c	Sat Oct 12 23:19:03 2002
@@ -1616,7 +1616,6 @@ issignal(td)
 		if (SIGISEMPTY(mask))		/* no signal to send */
 			return (0);
 		sig = sig_ffs(&mask);
-		prop = sigprop(sig);
 
 		_STOPEVENT(p, S_SIG, sig);
 
@@ -1648,14 +1647,6 @@ issignal(td)
 			PROC_LOCK(p);
 
 			/*
-			 * If the traced bit got turned off, go back up
-			 * to the top to rescan signals.  This ensures
-			 * that p_sig* and ps_sigact are consistent.
-			 */
-			if ((p->p_flag & P_TRACED) == 0)
-				continue;
-
-			/*
 			 * If parent wants us to take the signal,
 			 * then it will leave it in p->p_xstat;
 			 * otherwise we just look for signals again.
@@ -1673,7 +1664,17 @@ issignal(td)
 			if (SIGISMEMBER(p->p_sigmask, sig))
 				continue;
 			signotify(p);
+
+			/*
+			 * If the traced bit got turned off, go back up
+			 * to the top to rescan signals.  This ensures
+			 * that p_sig* and ps_sigact are consistent.
+			 */
+			if ((p->p_flag & P_TRACED) == 0)
+				continue;
 		}
+
+		prop = sigprop(sig);
 
 		/*
 		 * Decide whether the signal should be returned.

>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200210131511.g9DFBGbm000741>