[PATCH 2009-01-29] fix tcb init (wasn't resetting new fields); restrict PTRACE_SETOPTIONS to new kernels; output fixes

Denys Vlasenko dvlasenk at redhat.com
Mon Feb 23 13:45:32 UTC 2009


diff -x CVS -urpN 2009-01-28/ChangeLog 2009-01-29/ChangeLog
--- 2009-01-28/ChangeLog	2009-01-27 20:38:44.000000000 +0100
+++ 2009-01-29/ChangeLog	2009-01-28 20:00:54.000000000 +0100
@@ -1,3 +1,12 @@
+2009-01-28  Denys Vlasenko  <dvlasenk at redhat.com>
+
+	* process.c (internal_clone): Check and complain if pid value
+	looks insane.
+	* strace.c (alloc_tcb): Clear *all* fields in reused tcb.
+	(main): Query and rememeber uname() info on startup.
+	(handle_stopped_tcbs): Do not use PTRACE_SETOPTIONS on Linux < 2.6.29.
+	(printleader): Correct printing of "<unavailable>" markers.
+
 2009-01-27  Denys Vlasenko  <dvlasenk at redhat.com>
 
 	* strace.c (collect_stopped_tcbs): Guard against the case when
diff -x CVS -urpN 2009-01-28/process.c 2009-01-29/process.c
--- 2009-01-28/process.c	2009-01-26 20:09:38.000000000 +0100
+++ 2009-01-29/process.c	2009-01-28 20:00:54.000000000 +0100
@@ -34,7 +34,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: process.c,v 1.127 2009/01/26 19:09:38 vda_linux Exp $
+ *	$Id: process.c,v 1.128 2009/01/28 19:00:54 vda_linux Exp $
  */
 
 #include "defs.h"
@@ -877,19 +877,19 @@ setarg(tcp, argnum)
 
 #if defined SYS_clone || defined SYS_clone2
 int
-internal_clone(tcp)
-struct tcb *tcp;
+internal_clone(struct tcb *tcp)
 {
 	struct tcb *tcpchild;
-	int pid;
+	int pid, bpt;
+
 	if (entering(tcp)) {
 		if (!followfork)
 			return 0;
 		fork_tcb(tcp);
-		if (setbpt(tcp) < 0)
-			return 0;
+		setbpt(tcp);
+		return 0;
 	} else {
-		int bpt = tcp->flags & TCB_BPTSET;
+		bpt = tcp->flags & TCB_BPTSET;
 
 		if (!(tcp->flags & TCB_FOLLOWFORK))
 			return 0;
@@ -901,6 +901,15 @@ struct tcb *tcp;
 		}
 
 		pid = tcp->u_rval;
+		/* Should not happen, but bugs often cause bogus value here */
+		if (pid <= 1
+		 || (sizeof(pid) != sizeof(tcp->u_rval) && pid != tcp->u_rval)
+		) {
+			if (bpt)
+				clearbpt(tcp);
+			fprintf(stderr, "bogus clone() return value %lx!\n", tcp->u_rval);
+			return 0;
+		}
 
 #ifdef CLONE_PTRACE		/* See new setbpt code.  */
 		tcpchild = pid2tcb(pid);
@@ -1003,7 +1012,6 @@ Process %u resumed (parent %d ready)\n",
 			}
 		}
 #endif
-
  	}
 	return 0;
 }
diff -x CVS -urpN 2009-01-28/strace.c 2009-01-29/strace.c
--- 2009-01-28/strace.c	2009-01-27 20:38:44.000000000 +0100
+++ 2009-01-29/strace.c	2009-01-28 20:00:54.000000000 +0100
@@ -27,7 +27,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- *	$Id: strace.c,v 1.104 2009/01/27 19:38:44 vda_linux Exp $
+ *	$Id: strace.c,v 1.105 2009/01/28 19:00:54 vda_linux Exp $
  */
 
 #include "defs.h"
@@ -40,6 +40,7 @@
 #include <sys/resource.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
+#include <sys/utsname.h>
 #include <pwd.h>
 #include <grp.h>
 #include <string.h>
@@ -99,6 +100,8 @@ static int iflag = 0, interactive = 0, p
  */
 static bool daemonized_tracer = 0;
 
+static struct utsname utsname_buf;
+
 /* Sometimes we want to print only succeeding syscalls. */
 int not_failing_only = 0;
 
@@ -696,6 +699,8 @@ main(int argc, char *argv[])
 
 	progname = argv[0] ? argv[0] : "strace";
 
+	uname(&utsname_buf);
+
 	/* Allocate the initial tcbtab.  */
 	tcbtabsize = argc;	/* Surely enough for all -p args.  */
 	if ((tcbtab = calloc(tcbtabsize, sizeof tcbtab[0])) == NULL) {
@@ -1002,18 +1007,10 @@ alloc_tcb(int pid, int command_options_p
 	for (i = 0; i < tcbtabsize; i++) {
 		tcp = tcbtab[i];
 		if ((tcp->flags & TCB_INUSE) == 0) {
+			memset(tcp, 0, sizeof(*tcp));
 			tcp->pid = pid;
-			tcp->parent = NULL;
-			tcp->nchildren = 0;
-			tcp->nzombies = 0;
-#ifdef TCB_CLONE_THREAD
-			tcp->nclone_threads = tcp->nclone_detached = 0;
-			tcp->nclone_waiting = 0;
-#endif
 			tcp->flags = TCB_INUSE | TCB_STARTUP;
 			tcp->outf = outf; /* Initialise to current out file */
-			tcp->stime.tv_sec = 0;
-			tcp->stime.tv_usec = 0;
 			tcp->pfd = -1;
 			nprocs++;
 			if (command_options_parsed)
@@ -2579,7 +2576,18 @@ handle_stopped_tcbs(struct tcb *tcp)
 			 * execve's SIGTRAP with PTRACE_EVENT_EXEC.
 			 */
 			if (!ptrace_opts_set) {
+				char *p;
 				ptrace_opts_set = 1;
+
+				/* RHEL 2.6.18 definitely has crippling bugs */
+				/* Vanilla and Fedora 2.6.29 seems to work */
+				p = utsname_buf.release;
+				if (strtoul(p, &p, 10) < 2 || *p != '.')
+					goto tracing;
+				if (strtoul(++p, &p, 10) < 6 || *p != '.')
+					goto tracing;
+				if (strtoul(++p, &p, 10) < 29)
+					goto tracing;
 				/*
 				 * NB: even if this "succeeds", we can
 				 * revert back to SIGTRAP if we later see
@@ -2829,20 +2837,20 @@ va_dcl
 }
 
 void
-printleader(tcp)
-struct tcb *tcp;
+printleader(struct tcb *tcp)
 {
 	if (tcp_last) {
 		if (tcp_last->ptrace_errno) {
+			tcp_last->ptrace_errno = 0;
 			if (tcp_last->flags & TCB_INSYSCALL) {
-				tprintf(" <unavailable>)");
-				tabto(acolumn);
+				tprintf(" <unavailable ...>\n");
+				tcp_last->flags |= TCB_REPRINT;
+			} else {
+				tprintf("= ? <unavailable>\n");
 			}
-			tprintf("= ? <unavailable>\n");
-			tcp_last->ptrace_errno = 0;
 		} else if (!outfname || followfork < 2 || tcp_last == tcp) {
-			tcp_last->flags |= TCB_REPRINT;
 			tprintf(" <unfinished ...>\n");
+			tcp_last->flags |= TCB_REPRINT;
 		}
 	}
 	curcol = 0;






More information about the Strace-devel mailing list