diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2009-01-29 20:38:20 +0000 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2009-01-29 20:38:20 +0000 |
commit | 7a8bf065802f836901ae886317efcb4ed77cae7b (patch) | |
tree | c9ede8a711ae077ed977f343c3de06ce2891df82 | |
parent | 7e0615f3aecc023e2756a83bdf113c5ceaac431d (diff) | |
download | strace-7a8bf065802f836901ae886317efcb4ed77cae7b.tar.gz |
* strace.c (newoutf): Prevent -o FILENAME overflowing the stack.
(startup_attach): Fix wrong pid in "Process <PID> attached".
(handle_group_exit): Do not consider exit to be spurious if
tcb has TCB_STARTUP bit set - we can attach to the task
right before its death, it can legitimately happen.
(handle_stopped_tcbs): Ditto.
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | strace.c | 70 |
2 files changed, 44 insertions, 37 deletions
@@ -1,9 +1,18 @@ +2009-01-29 Denys Vlasenko <dvlasenk@redhat.com> + + * strace.c (newoutf): Prevent -o FILENAME overflowing the stack. + (startup_attach): Fix wrong pid in "Process <PID> attached". + (handle_group_exit): Do not consider exit to be spurious if + tcb has TCB_STARTUP bit set - we can attach to the task + right before its death, it can legitimately happen. + (handle_stopped_tcbs): Ditto. + 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. + (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. @@ -355,10 +355,10 @@ static int newoutf(struct tcb *tcp) { if (outfname && followfork > 1) { - char name[MAXPATHLEN]; + char name[520 + sizeof(int) * 3]; FILE *fp; - sprintf(name, "%s.%u", outfname, tcp->pid); + sprintf(name, "%.512s.%u", outfname, tcp->pid); if ((fp = strace_fopen(name, "w")) == NULL) return -1; tcp->outf = fp; @@ -420,7 +420,7 @@ startup_attach(void) #else /* !USE_PROCFS */ # ifdef LINUX if (followfork && !daemonized_tracer) { - char procdir[MAXPATHLEN]; + char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3]; DIR *dir; sprintf(procdir, "/proc/%d/task", tcp->pid); @@ -430,15 +430,13 @@ startup_attach(void) struct dirent *de; int tid; while ((de = readdir(dir)) != NULL) { - if (de->d_fileno == 0 || - de->d_name[0] == '.') + if (de->d_fileno == 0) continue; tid = atoi(de->d_name); if (tid <= 0) continue; ++ntid; - if (ptrace(PTRACE_ATTACH, tid, - (char *) 1, 0) < 0) + if (ptrace(PTRACE_ATTACH, tid, (char *) 1, 0) < 0) ++nerr; else if (tid != tcbtab[tcbi]->pid) { tcp = alloctcb(tid); @@ -456,25 +454,21 @@ startup_attach(void) } } closedir(dir); - if (nerr == ntid) { + ntid -= nerr; + if (ntid == 0) { perror("attach: ptrace(PTRACE_ATTACH, ...)"); droptcb(tcp); continue; } if (!qflag) { - ntid -= nerr; - if (ntid > 1) - fprintf(stderr, "\ -Process %u attached with %u threads - interrupt to quit\n", - tcp->pid, ntid); - else - fprintf(stderr, "\ -Process %u attached - interrupt to quit\n", - tcp->pid); + fprintf(stderr, ntid > 1 +? "Process %u attached with %u threads - interrupt to quit\n" +: "Process %u attached - interrupt to quit\n", + tcbtab[tcbi]->pid, ntid); } continue; - } - } + } /* if (opendir worked) */ + } /* if (-f) */ # endif if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) { perror("attach: ptrace(PTRACE_ATTACH, ...)"); @@ -2205,20 +2199,25 @@ handle_group_exit(struct tcb *tcp, int sig) { /* We need to locate our records of all the clone threads related to TCP, either its children or siblings. */ - struct tcb *leader = ((tcp->flags & TCB_CLONE_THREAD) - ? tcp->parent - : tcp->nclone_detached > 0 - ? tcp : NULL); + struct tcb *leader = NULL; + + if (tcp->flags & TCB_CLONE_THREAD) + leader = tcp->parent; + else if (tcp->nclone_detached > 0) + leader = tcp; if (sig < 0) { - if (leader != NULL && leader != tcp && - !(leader->flags & TCB_GROUP_EXITING)) + if (leader != NULL && leader != tcp + && !(leader->flags & TCB_GROUP_EXITING) + && !(tcp->flags & TCB_STARTUP) + ) { fprintf(stderr, "PANIC: handle_group_exit: %d leader %d\n", tcp->pid, leader ? leader->pid : -1); - /* TCP no longer exists therefore you must not detach () it. */ + } + /* TCP no longer exists therefore you must not detach() it. */ #ifndef USE_PROCFS - resume_from_tcp (tcp); + resume_from_tcp(tcp); #endif droptcb(tcp); /* Already died. */ } @@ -2498,20 +2497,19 @@ handle_stopped_tcbs(struct tcb *tcp) if (pid == strace_child) exit_code = WEXITSTATUS(status); if (debug) - fprintf(stderr, "pid %u exited\n", pid); - if ((tcp->flags & TCB_ATTACHED) + fprintf(stderr, "pid %u exited with %d\n", pid, WEXITSTATUS(status)); + if ((tcp->flags & (TCB_ATTACHED|TCB_STARTUP)) == TCB_ATTACHED #ifdef TCB_GROUP_EXITING - && !(tcp->parent && (tcp->parent->flags & - TCB_GROUP_EXITING)) + && !(tcp->parent && (tcp->parent->flags & TCB_GROUP_EXITING)) && !(tcp->flags & TCB_GROUP_EXITING) #endif - ) + ) { fprintf(stderr, - "PANIC: attached pid %u exited\n", - pid); + "PANIC: attached pid %u exited with %d\n", + pid, WEXITSTATUS(status)); + } if (tcp == tcp_last) { - if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) - == TCB_INSYSCALL) + if ((tcp->flags & (TCB_INSYSCALL|TCB_REPRINT)) == TCB_INSYSCALL) tprintf(" <unfinished ... exit status %d>\n", WEXITSTATUS(status)); tcp_last = NULL; |