>From e406ae13301618cd4d020de826ae9c3eaa192bdf Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <dvlas...@redhat.com>
Date: Tue, 13 Jan 2009 18:30:55 +0000
Subject: [PATCH] Make strace correctly handle SIGTRAP produced by e.g.
 kill(2) and by trapping instruction.

* strace.c (ptrace_stop_sig): Define.
(detach): Use it instead of SIGTRAP constant.
(trace): Attempt to set PTRACE_O_TRACESYSGOOD and
PTRACE_O_TRACEEXEC options on each newly attached process,
distinquish between SIGTRAP and (SIGTRAP | 0x80) stops.
Fixes RH#162774 "strace ignores int3 SIGTRAP".
---
 strace.c |   80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 78 insertions(+), 2 deletions(-)

diff --git a/strace.c b/strace.c
index 7294e8e..c63254a 100644
--- a/strace.c
+++ b/strace.c
@@ -104,6 +104,8 @@ int not_failing_only = 0;
 
 static int exit_code = 0;
 static int strace_child = 0;
+static int ptrace_stop_sig = SIGTRAP;
+static bool ptrace_opts_set;
 
 static char *username = NULL;
 uid_t run_uid;
@@ -1622,7 +1624,7 @@ int sig;
                                break;
                        }
                        error = ptrace_restart(PTRACE_CONT, tcp,
-                                       WSTOPSIG(status) == SIGTRAP ? 0
+                                       WSTOPSIG(status) == ptrace_stop_sig ? 0
                                        : WSTOPSIG(status));
                        if (error < 0)
                                break;
@@ -2484,10 +2486,84 @@ Process %d attached (waiting for parent)\n",
                                        return -1;
                                }
                        }
+/* Add more OSes after you verified it works for them. */
+/* PTRACE_SETOPTIONS may be an enum, not a #define.
+ * But sometimes we can test for it by checking PT_SETOPTIONS.
+ */
+#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
+# ifndef PTRACE_O_TRACESYSGOOD
+#  define PTRACE_O_TRACESYSGOOD 0x00000001
+# endif
+# ifndef PTRACE_O_TRACEEXEC
+#  define PTRACE_O_TRACEEXEC    0x00000010
+# endif
+# ifndef PTRACE_EVENT_EXEC
+#  define PTRACE_EVENT_EXEC     4
+# endif
+                       /*
+                        * Ask kernel to set signo to SIGTRAP | 0x80
+                        * on ptrace-generated SIGTRAPs, and mark
+                        * execve's SIGTRAP with PTRACE_EVENT_EXEC.
+                        */
+                       if (!ptrace_opts_set) {
+                               ptrace_opts_set = 1;
+                               /*
+                                * NB: even if this "succeeds", we can
+                                * revert back to SIGTRAP if we later see
+                                * that it didnt really work.
+                                * Old kernels are known to lie here.
+                                */
+                               if (ptrace(PTRACE_SETOPTIONS, pid, (char *) 0,
+                                       (void *) (PTRACE_O_TRACESYSGOOD | 
PTRACE_O_TRACEEXEC)) == 0)
+                                       ptrace_stop_sig = SIGTRAP | 0x80;
+                       }
+#endif
                        goto tracing;
                }
 
-               if (WSTOPSIG(status) != SIGTRAP) {
+#if defined LINUX && (defined PTRACE_SETOPTIONS || defined PT_SETOPTIONS)
+               if (ptrace_stop_sig != SIGTRAP && WSTOPSIG(status) == SIGTRAP) {
+                       /*
+                        * We told ptrace to report SIGTRAP | 0x80 on this 
process
+                        * but got bare SIGTRAP. This can be a genuine SIGTRAP:
+                        * kill(pid, SIGTRAP), trap insn, etc;
+                        * 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;
+                       } else {
+                               /* Take a better look...  */
+                               siginfo_t si;
+                               ptrace(PTRACE_GETSIGINFO, pid, (void*) 0, 
(void*) &si);
+                               /*
+                                * Check some fields to make sure we see
+                                * real SIGTRAP.
+                                * Otherwise interpret it as ptrace stop.
+                                * Real SIGTRAPs (int3 insn on x86, kill() etc)
+                                * have these values:
+                                * int3:                   kill -TRAP $pid:
+                                * si_signo:5 (SIGTRAP)    si_signo:5 (SIGTRAP)
+                                * si_errno:0              si_errno:(?)
+                                * si_code:128 (SI_KERNEL) si_code:0 (SI_USER)
+                                * si_pid:0                si_pid:(>0?)
+                                * si_band:0               si_band:(?)
+                                * Ptrace stops have garbage there instead.
+                                */
+                               if (si.si_signo != SIGTRAP
+                                || (si.si_code != SI_KERNEL && si.si_code != 
SI_USER)
+                               ) {
+                                       fprintf(stderr, "bogus SIGTRAP 
(si_code:%x), assuming old kernel\n", si.si_code);
+                                       ptrace_stop_sig = SIGTRAP;
+                               }
+                       }
+               }
+#endif
+
+               if (WSTOPSIG(status) != ptrace_stop_sig) {
+                       /* This isn't a ptrace stop.  */
+
                        if (WSTOPSIG(status) == SIGSTOP &&
                                        (tcp->flags & TCB_SIGTRAPPED)) {
                                /*
-- 
1.6.5.2



Andreas.

-- 
Andreas Schwab, sch...@redhat.com
GPG Key fingerprint = D4E8 DBE3 3813 BB5D FA84  5EC7 45C6 250E 6F00 984E
"And now for something completely different."

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to