* defs.h (TCB_PTRACE_OPTIONS) [LINUX && PTRACE_SETOPTIONS]:
Define.
* process.c (internal_fork): Copy TCB_PTRACE_OPTIONS flag to
child.
(internal_exec): Only set TCB_WAITEXECVE on entering.
* strace.c (set_ptrace_options, is_ptrace_stop)
(is_post_execve_trap): Define.
(proc_open): Use them.
---
 defs.h    |   12 +++++++++
 process.c |   10 +++++--
 strace.c  |   79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 97 insertions(+), 4 deletions(-)

diff --git a/defs.h b/defs.h
index 4797e96..9001a85 100644
--- a/defs.h
+++ b/defs.h
@@ -378,6 +378,18 @@ struct tcb {
 # define TCB_CLONE_DETACHED 04000 /* CLONE_DETACHED set in creating syscall */
 # define TCB_CLONE_THREAD  010000 /* CLONE_THREAD set in creating syscall */
 # define TCB_GROUP_EXITING 020000 /* TCB_EXITING was exit_group, not _exit */
+# 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
+#  define TCB_PTRACE_OPTIONS 040000 /* PTRACE_SETOPTIONS called */
+# endif
 # include <sys/syscall.h>
 # ifndef __NR_exit_group
 # /* Hack: Most headers around are too old to have __NR_exit_group.  */
diff --git a/process.c b/process.c
index c69e45e..cc02921 100644
--- a/process.c
+++ b/process.c
@@ -866,6 +866,9 @@ internal_fork(struct tcb *tcp)
                                clearbpt(tcpchild);
 
                        tcpchild->flags &= ~(TCB_SUSPENDED|TCB_STARTUP);
+#ifdef TCB_PTRACE_OPTIONS
+                       tcpchild->flags |= tcp->flags & TCB_PTRACE_OPTIONS;
+#endif
                        if (ptrace_restart(PTRACE_SYSCALL, tcpchild, 0) < 0)
                                return -1;
 
@@ -1732,9 +1735,10 @@ struct tcb *tcp;
                fixvfork(tcp);
 #endif /* SUNOS4 */
 #if defined LINUX && defined TCB_WAITEXECVE
-       if (exiting(tcp) && syserror(tcp))
-               tcp->flags &= ~TCB_WAITEXECVE;
-       else
+       if (exiting(tcp)) {
+               if (syserror(tcp))
+                       tcp->flags &= ~TCB_WAITEXECVE;
+       } else
                tcp->flags |= TCB_WAITEXECVE;
 #endif /* LINUX && TCB_WAITEXECVE */
        return 0;
diff --git a/strace.c b/strace.c
index 2fb75c9..701d366 100644
--- a/strace.c
+++ b/strace.c
@@ -2253,6 +2253,75 @@ handle_group_exit(struct tcb *tcp, int sig)
 }
 #endif
 
+#ifdef TCB_PTRACE_OPTIONS
+
+static int use_ptrace_setoptions = 1;
+static int probe_ptrace_setoptions = PTRACE_O_TRACESYSGOOD | 
PTRACE_O_TRACEEXEC;
+
+static void
+set_ptrace_options(struct tcb *tcp)
+{
+       if (!use_ptrace_setoptions)
+               return;
+
+       /*
+        * Ask kernel to set signo to SIGTRAP | 0x80
+        * on ptrace-generated SIGTRAPs, and mark
+        * execve's SIGTRAP with PTRACE_EVENT_EXEC.
+        */
+       if (ptrace(PTRACE_SETOPTIONS, tcp->pid, (char *) 0,
+                  PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC) == 0)
+               tcp->flags |= TCB_PTRACE_OPTIONS;
+       else if (errno != ESRCH)
+               use_ptrace_setoptions = 0;
+}
+
+static int
+is_ptrace_stop(struct tcb *tcp, int status)
+{
+       if (!(tcp->flags & TCB_PTRACE_OPTIONS))
+               return WSTOPSIG(status) == SIGTRAP;
+
+       if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {
+               /* PTRACE_O_TRACESYSGOOD works. */
+               probe_ptrace_setoptions &= PTRACE_O_TRACESYSGOOD;
+               return 1;
+       }
+       if (WSTOPSIG(status) == SIGTRAP &&
+           ((unsigned)status >> 16) == PTRACE_EVENT_EXEC) {
+               /* PTRACE_O_TRACEEXEC works. */
+               probe_ptrace_setoptions &= PTRACE_O_TRACEEXEC;
+               return 1;
+       }
+
+       if ((WSTOPSIG(status) == SIGTRAP && probe_ptrace_setoptions))
+               return 1;
+       return 0;
+}
+
+static int
+is_post_execve_trap(struct tcb *tcp, int status)
+{
+       if (!use_ptrace_setoptions)
+               return 0;
+       
+       if (WSTOPSIG(status) == SIGTRAP) {
+               if (((unsigned)status >> 16) == PTRACE_EVENT_EXEC)
+                       return 1;
+               /* A SIGTRAP received before the first ptrace stop
+                  after attaching must be the post-execve trap.  */
+               if ((tcp->flags & 
(TCB_STARTUP|TCB_ATTACHED|TCB_PTRACE_OPTIONS)) ==
+                   (TCB_STARTUP|TCB_ATTACHED))
+                       return 1;
+       }
+       return 0;
+}
+#else
+#define set_ptrace_options(tcp)
+#define is_ptrace_stop(tcp, status) (WSTOPSIG(status) == SIGTRAP)
+#define is_post_execve_trap(tcp, status) 0
+#endif
+
 static int
 trace()
 {
@@ -2465,10 +2534,11 @@ Process %d attached (waiting for parent)\n",
                                        return -1;
                                }
                        }
+                       set_ptrace_options(tcp);
                        goto tracing;
                }
 
-               if (WSTOPSIG(status) != SIGTRAP) {
+               if (!is_ptrace_stop(tcp, status)) {
                        if (WSTOPSIG(status) == SIGSTOP &&
                                        (tcp->flags & TCB_SIGTRAPPED)) {
                                /*
@@ -2533,6 +2603,13 @@ Process %d attached (waiting for parent)\n",
                /* we handled the STATUS, we are permitted to interrupt now. */
                if (interrupted)
                        return 0;
+               /* Ignore post-execve trap. */
+               if (is_post_execve_trap(tcp, status)) {
+#ifdef TCB_WAITEXECVE
+                       tcp->flags &= ~TCB_WAITEXECVE;
+#endif
+                       goto tracing;
+               }
                if (trace_syscall(tcp) < 0 && !tcp->ptrace_errno) {
                        /* ptrace() failed in trace_syscall() with ESRCH.
                         * Likely a result of process disappearing mid-flight.
-- 
1.7.0.1


Andreas.

-- 
Andreas Schwab, [email protected]
GPG Key fingerprint = D4E8 DBE3 3813 BB5D FA84  5EC7 45C6 250E 6F00 984E
"And now for something completely different."

------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
Strace-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to