]> granicus.if.org Git - strace/commitdiff
* process.c (internal_clone): Check and complain if pid value
authorDenys Vlasenko <dvlasenk@redhat.com>
Wed, 28 Jan 2009 19:00:54 +0000 (19:00 +0000)
committerDenys Vlasenko <dvlasenk@redhat.com>
Wed, 28 Jan 2009 19:00:54 +0000 (19:00 +0000)
looks insane.
* strace.c (alloc_tcb): Clear *all* fields in reused tcb.
(main): Query and remember uname() info on startup.
(handle_stopped_tcbs): Do not use PTRACE_SETOPTIONS on Linux < 2.6.29.
(printleader): Correct printing of "<unavailable>" markers.

ChangeLog
process.c
strace.c

index e8ccda48c218c8608698d6b58a2b407e693c7529..24f0fe4573f50534d5b0c78fc42137c5102c52a2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2009-01-28  Denys Vlasenko  <dvlasenk@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@redhat.com>
 
        * strace.c (collect_stopped_tcbs): Guard against the case when
index 23e44f6df7a8d86ae614f52c8aa043f0e9942b1a..d61f54857bcde225c9dc12de014c1dcd687d2ec0 100644 (file)
--- a/process.c
+++ b/process.c
@@ -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;
 }
index 62073e4d6251be1711535b801f664a2f5b5b8b7c..af485619a6c8dcbd46bf0cd73696a743e7138d3b 100644 (file)
--- a/strace.c
+++ b/strace.c
@@ -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, pflag_seen = 0, rflag = 0, tflag = 0;
  */
 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_parsed)
        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;