From 7e0615f3aecc023e2756a83bdf113c5ceaac431d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 28 Jan 2009 19:00:54 +0000 Subject: [PATCH] * 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 remember uname() info on startup. (handle_stopped_tcbs): Do not use PTRACE_SETOPTIONS on Linux < 2.6.29. (printleader): Correct printing of "" markers. --- ChangeLog | 9 +++++++++ process.c | 22 +++++++++++++++------- strace.c | 40 ++++++++++++++++++++++++---------------- 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index e8ccda48..24f0fe45 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-01-28 Denys Vlasenko + + * 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 "" markers. + 2009-01-27 Denys Vlasenko * strace.c (collect_stopped_tcbs): Guard against the case when diff --git a/process.c b/process.c index 23e44f6d..d61f5485 100644 --- 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; } diff --git a/strace.c b/strace.c index 62073e4d..af485619 100644 --- a/strace.c +++ b/strace.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -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(" )"); - tabto(acolumn); + tprintf(" \n"); + tcp_last->flags |= TCB_REPRINT; + } else { + tprintf("= ? \n"); } - tprintf("= ? \n"); - tcp_last->ptrace_errno = 0; } else if (!outfname || followfork < 2 || tcp_last == tcp) { - tcp_last->flags |= TCB_REPRINT; tprintf(" \n"); + tcp_last->flags |= TCB_REPRINT; } } curcol = 0; -- 2.40.0