]> granicus.if.org Git - strace/commitdiff
* defs.h: Update a comment. No code changes.
authorDenys Vlasenko <dvlasenk@redhat.com>
Sat, 17 Jan 2009 01:06:18 +0000 (01:06 +0000)
committerDenys Vlasenko <dvlasenk@redhat.com>
Sat, 17 Jan 2009 01:06:18 +0000 (01:06 +0000)
* strace.c (handle_stopped_tcbs): Discard all execve stops
and clear TCB_WAITEXECVE bit.
* syscall.c (get_scno): Add the code to not mistakenly
treat ptrace stop as execve stop (execve stops can be blocked
by traced program).
Fixes RH#477775 "strace hangs if the target process blocks SIGTRAP".

ChangeLog
defs.h
strace.c
syscall.c

index 0102ce87ef9dac5cadd5c8f11a852763f8dbff99..e55baa914c347c49d2850c654ee08ebf860d2141 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2009-01-17  Denys Vlasenko  <dvlasenk@redhat.com>
+
+       * defs.h: Update a comment. No code changes.
+       * strace.c (handle_stopped_tcbs): Discard all execve stops
+       and clear TCB_WAITEXECVE bit.
+       * syscall.c (get_scno): Add the code to not mistakenly
+       treat ptrace stop as execve stop (execve stops can be blocked
+       by traced program).
+       Fixes RH#477775 "strace hangs if the target process blocks SIGTRAP".
+
 2009-01-17  Denys Vlasenko  <dvlasenk@redhat.com>
 
        * process.c: Add a comment. No code changes.
diff --git a/defs.h b/defs.h
index 1366a6efb44e1f34c82ab89097cdbaa799783ab5..d2315e22a324a39b71c8e4be50b03dfdd4423505 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -363,9 +363,17 @@ struct tcb {
 #define TCB_FOLLOWFORK 00400   /* Process should have forks followed */
 #define TCB_REPRINT    01000   /* We should reprint this syscall on exit */
 #ifdef LINUX
-/* x86 does not need TCB_WAITEXECVE.
+/* TCB_WAITEXECVE bit means "ignore next SIGTRAP, it's execve exit stop".
+ * it is not reliable if traced program masks SIGTRAP.
+ *
+ * x86 does not need TCB_WAITEXECVE.
  * It can detect execve's SIGTRAP by looking at eax/rax.
  * See "stray syscall exit: eax = " message in syscall_fixup().
+ *
+ * Note that on newer kernels, we use ptrace options and therefore
+ * can filter out execve stops reliably on any architecture,
+ * without using TCB_WAITEXECVE flag.
+ * I guess we can remove it from the source somewhere around year 2010 :)
  */
 # if defined(ALPHA) || defined(SPARC) || defined(SPARC64) || defined(POWERPC) || defined(IA64) || defined(HPPA) || defined(SH) || defined(SH64) || defined(S390) || defined(S390X) || defined(ARM) || defined(MIPS) || defined(BFIN)
 #  define TCB_WAITEXECVE 02000 /* ignore SIGTRAP after exceve */
index 80d468a29d035b26b7e479435501672c5b5fbb89..8c387f9e659afaf9e6014db22c19a16ee2b13048 100644 (file)
--- a/strace.c
+++ b/strace.c
@@ -2576,12 +2576,17 @@ handle_stopped_tcbs(struct tcb *tcp)
                         * but be paranoid about it.
                         */
                        if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
-                               /* It's post-exec ptrace stop.  */
-                               /* Set WSTOPSIG(status) = (SIGTRAP | 0x80).  */
-                               status |= 0x8000;
+                               /* It's post-exec ptrace stop. Ignore it,
+                                * we will get syscall exit ptrace stop later.
+                                */
+#ifdef TCB_WAITEXECVE
+                               tcp->flags &= ~TCB_WAITEXECVE;
+#endif
+                               goto tracing;
                        } else {
                                /* Take a better look...  */
                                siginfo_t si;
+                               si.si_signo = 0;
                                ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (void*) &si);
                                /*
                                 * Check some fields to make sure we see
index 40fd985922dbe5f227bab66b46eccbe6e1a22787..3fbacb297732167e036833bf6d16bb46b88631b9 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -976,26 +976,47 @@ struct tcb *tcp;
        }
 #elif defined(IA64)
 #      define IA64_PSR_IS      ((long)1 << 34)
-       if (upeek (tcp, PT_CR_IPSR, &psr) >= 0)
+       if (upeek(tcp, PT_CR_IPSR, &psr) >= 0)
                ia32 = (psr & IA64_PSR_IS) != 0;
        if (!(tcp->flags & TCB_INSYSCALL)) {
                if (ia32) {
                        if (upeek(tcp, PT_R1, &scno) < 0)       /* orig eax */
                                return -1;
                } else {
-                       if (upeek (tcp, PT_R15, &scno) < 0)
+                       if (upeek(tcp, PT_R15, &scno) < 0)
                                return -1;
                }
                /* Check if we return from execve. */
                if (tcp->flags & TCB_WAITEXECVE) {
+#if defined PTRACE_GETSIGINFO
+                       siginfo_t si;
+
+                       tcp->flags &= ~TCB_WAITEXECVE;
+                       /* If SIGTRAP is masked, execve's magic SIGTRAP
+                        * is not delivered. We end up here on a subsequent
+                        * ptrace stop instead. Luckily, we can check
+                        * for the type of this SIGTRAP. execve's magic one
+                        * has 0 (SI_USER) in si.si_code, ptrace stop has 5.
+                        * (I don't know why 5).
+                        */
+                       si.si_code = SI_USER;
+                       /* If PTRACE_GETSIGINFO fails, we assume it's
+                        * magic SIGTRAP. Moot anyway, PTRACE_GETSIGINFO
+                        * doesn't fail.
+                        */
+                       ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, (void*) &si);
+                       if (si.si_code == SI_USER)
+                               return 0;
+#else
                        tcp->flags &= ~TCB_WAITEXECVE;
                        return 0;
+#endif
                }
        } else {
                /* syscall in progress */
-               if (upeek (tcp, PT_R8, &r8) < 0)
+               if (upeek(tcp, PT_R8, &r8) < 0)
                        return -1;
-               if (upeek (tcp, PT_R10, &r10) < 0)
+               if (upeek(tcp, PT_R10, &r10) < 0)
                        return -1;
        }
 #elif defined (ARM)