+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
#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;
}
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);
}
}
#endif
-
}
return 0;
}
#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>
*/
static bool daemonized_tracer = 0;
+static struct utsname utsname_buf;
+
/* Sometimes we want to print only succeeding syscalls. */
int not_failing_only = 0;
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) {
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)
* 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
}
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;