]> granicus.if.org Git - strace/commitdiff
Implement simultaneous use of -p option and tracing of a command
authorDmitry V. Levin <ldv@altlinux.org>
Fri, 22 Jan 2016 14:37:14 +0000 (14:37 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Fri, 22 Jan 2016 19:37:11 +0000 (19:37 +0000)
* strace.c (init): Allow -p option along with a command.
(startup_child): In -D mode, record the parent of the tracer process
as strace_child.
(startup_attach): Save trace_tracer_pid before -D mode fork.
When tracing a command in -f mode, do not check for the command's
threads as it has no threads at this moment.
Never attach to the tracer process.
In -D mode, never attach to the parent of the tracer process,
terminate that process only once at the end of startup_attach,
and reset strace_child.
* strace.1: Document that -p option can be used along with tracing
of a command.
* NEWS: Mention it.
* tests/attach-p-cmd-cmd.c: New file.
* tests/attach-p-cmd-p.c: Likewise.
* tests/attach-p-cmd.test: New test.
* tests/.gitignore: Add attach-p-cmd-cmd and attach-p-cmd-p.
* tests/Makefile.am (check_PROGRAMS): Likewise.
(TESTS): Add attach-p-cmd.test.

This fixes Debian bug #549942.

NEWS
strace.1
strace.c
tests/.gitignore
tests/Makefile.am
tests/attach-p-cmd-cmd.c [new file with mode: 0644]
tests/attach-p-cmd-p.c [new file with mode: 0644]
tests/attach-p-cmd.test [new file with mode: 0755]

diff --git a/NEWS b/NEWS
index ceddf0896a571f984c4a37c84e11607fbe64975e..a7520d661bda7802d15f3adedea6cd2cae419ad7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,8 @@ Noteworthy changes in release ?.?? (????-??-??)
 ===============================================
 
 * Improvements
+  * Implemented simultaneous use of -p option and tracing of a command.
+    (addresses Debian bug #549942).
   * Enhanced decoding of personality, sched_getaffinity,
     and sched_setaffinity syscalls.
   * Enhanced decoding of getxpid, getxuid, and getxgid syscalls on alpha.
index 6d5bcbad28d66ad7cb2cd12da215710b14aeb7b1..429cdfc6556138a379c8d8d3e1a93b16b1528fc3 100644 (file)
--- a/strace.1
+++ b/strace.1
@@ -530,8 +530,13 @@ will respond by detaching itself from the traced process(es)
 leaving it (them) to continue running.
 Multiple
 .B \-p
-options can be used to attach to many processes.
--p "`pidof PROG`" syntax is supported.
+options can be used to attach to many processes in addition to
+.I command
+(which is optional if at least one
+.B \-p
+option is given).
+.B \-p
+"`pidof PROG`" syntax is supported.
 .TP
 .BI "\-P " path
 Trace only system calls accessing
index 7792a5c88e609d78e4aa7ba12d9ca7bd555c36fb..614b85f9bf0282e48e794bb1e3260301248087e4 100644 (file)
--- a/strace.c
+++ b/strace.c
@@ -973,6 +973,7 @@ process_opt_p_list(char *opt)
 static void
 startup_attach(void)
 {
+       pid_t parent_pid = strace_tracer_pid;
        unsigned int tcbi;
        struct tcb *tcp;
 
@@ -1015,7 +1016,13 @@ startup_attach(void)
                if (tcp->flags & TCB_ATTACHED)
                        continue; /* no, we already attached it */
 
-               if (followfork && !daemonized_tracer) {
+               if (tcp->pid == parent_pid || tcp->pid == strace_tracer_pid) {
+                       errno = EPERM;
+                       perror_msg("attach: %d", tcp->pid);
+                       droptcb(tcp);
+                       continue;
+               }
+               if (followfork && tcp->pid != strace_child) {
                        char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
                        DIR *dir;
 
@@ -1092,18 +1099,19 @@ startup_attach(void)
                if (debug_flag)
                        error_msg("attach to pid %d (main) succeeded", tcp->pid);
 
-               if (daemonized_tracer) {
-                       /*
-                        * Make parent go away.
-                        * Also makes grandparent's wait() unblock.
-                        */
-                       kill(getppid(), SIGKILL);
-               }
-
                if (!qflag)
                        error_msg("Process %u attached", tcp->pid);
        } /* for each tcbtab[] */
 
+       if (daemonized_tracer) {
+               /*
+                * Make parent go away.
+                * Also makes grandparent's wait() unblock.
+                */
+               kill(parent_pid, SIGKILL);
+               strace_child = 0;
+       }
+
  ret:
        if (interactive)
                sigprocmask(SIG_SETMASK, &empty_set, NULL);
@@ -1317,11 +1325,10 @@ startup_child(char **argv)
                newoutf(tcp);
        }
        else {
-               /* With -D, we are *child* here, IOW: different pid. Fetch it: */
+               /* With -D, we are *child* here, the tracee is our parent. */
+               strace_child = strace_tracer_pid;
                strace_tracer_pid = getpid();
-               /* The tracee is our parent: */
-               pid = getppid();
-               alloctcb(pid);
+               alloctcb(strace_child);
                /* attaching will be done later, by startup_attach */
                /* note: we don't do newoutf(tcp) here either! */
 
@@ -1619,13 +1626,12 @@ init(int argc, char *argv[])
        memset(acolumn_spaces, ' ', acolumn);
        acolumn_spaces[acolumn] = '\0';
 
-       /* Must have PROG [ARGS], or -p PID. Not both. */
-       if (!argv[0] == !nprocs) {
+       if (!argv[0] && !nprocs) {
                error_msg_and_help("must have PROG [ARGS] or -p PID");
        }
 
-       if (nprocs != 0 && daemonized_tracer) {
-               error_msg_and_help("-D and -p are mutually exclusive");
+       if (!argv[0] && daemonized_tracer) {
+               error_msg_and_help("PROG [ARGS] must be specified with -D");
        }
 
        if (!followfork)
@@ -1722,9 +1728,9 @@ init(int argc, char *argv[])
                opt_intr = INTR_WHILE_WAIT;
 
        /* argv[0]      -pPID   -oFILE  Default interactive setting
-        * yes          0       0       INTR_WHILE_WAIT
+        * yes          *       0       INTR_WHILE_WAIT
         * no           1       0       INTR_WHILE_WAIT
-        * yes          0       1       INTR_NEVER
+        * yes          *       1       INTR_NEVER
         * no           1       1       INTR_WHILE_WAIT
         */
 
index 4f552d6b35b2e342309e9aa29581b4e594cd25c8..207a9b2e0a5bfc8544cc6b3e8a630c622530f975 100644 (file)
@@ -8,6 +8,8 @@
 _newselect
 adjtimex
 aio
+attach-p-cmd-cmd
+attach-p-cmd-p
 bpf
 caps
 clock_nanosleep
index 653503079cf5db119a2a2360e976f2c7d8fdb443..f6345836bdfa517c64d38985750d7d2976199047 100644 (file)
@@ -56,6 +56,8 @@ check_PROGRAMS = \
        _newselect \
        adjtimex \
        aio \
+       attach-p-cmd-cmd \
+       attach-p-cmd-p \
        bpf \
        caps \
        clock_nanosleep \
@@ -299,6 +301,7 @@ TESTS = \
        xettimeofday.test \
        \
        count.test \
+       attach-p-cmd.test \
        detach-sleeping.test \
        detach-stopped.test \
        detach-running.test \
diff --git a/tests/attach-p-cmd-cmd.c b/tests/attach-p-cmd-cmd.c
new file mode 100644 (file)
index 0000000..28f5e35
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * This file is part of attach-p-cmd strace test.
+ *
+ * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tests.h"
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int
+main(void)
+{
+       static const char text[] = "attach-p-cmd.test cmd";
+       assert(chdir(text) == -1);
+       pid_t pid = getpid();
+       printf("%-5d chdir(\"%s\") = -1 ENOENT (%m)\n"
+              "%-5d +++ exited with 0 +++\n", pid, text, pid);
+       return 0;
+}
diff --git a/tests/attach-p-cmd-p.c b/tests/attach-p-cmd-p.c
new file mode 100644 (file)
index 0000000..528d35a
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * This file is part of attach-p-cmd strace test.
+ *
+ * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tests.h"
+#include <assert.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+static void
+handler(int signo)
+{
+       _exit(!chdir("attach-p-cmd.test -p"));
+}
+
+int
+main(int ac, char **av)
+{
+       if (ac < 2)
+               error_msg_and_fail("missing operand");
+
+       if (ac > 2)
+               error_msg_and_fail("extra operand");
+
+       const sigset_t set = {};
+       const struct sigaction act = { .sa_handler = handler };
+       const struct itimerval itv = { .it_value.tv_sec = atoi(av[1]) };
+
+       assert(sigaction(SIGALRM, &act, NULL) == 0);
+       assert(sigprocmask(SIG_SETMASK, &set, NULL) == 0);
+       if (setitimer(ITIMER_REAL, &itv, NULL))
+               perror_msg_and_skip("setitimer");
+
+       for (;;);
+
+       return 0;
+}
diff --git a/tests/attach-p-cmd.test b/tests/attach-p-cmd.test
new file mode 100755 (executable)
index 0000000..de3f4cd
--- /dev/null
@@ -0,0 +1,54 @@
+#!/bin/sh
+#
+# Check that simultaneous use of -p option and tracing of a command works.
+#
+# Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+#    derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+. "${srcdir=.}/init.sh"
+
+run_prog_skip_if_failed \
+       kill -0 $$
+run_prog ./attach-p-cmd-cmd > /dev/null
+run_prog ./attach-p-cmd-p 1 > /dev/null
+
+OUT="$LOG.out"
+./set_ptracer_any ./attach-p-cmd-p 1 > "$OUT" &
+tracee_pid=$!
+
+while ! [ -s "$OUT" ]; do
+       kill -0 $tracee_pid 2> /dev/null ||
+               fail_ 'set_ptracer_any sleep failed'
+done
+
+run_strace -a30 -echdir -p $tracee_pid ./attach-p-cmd-cmd > "$OUT"
+{
+printf '%-5d --- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} ---\n' $tracee_pid
+printf '%-5d chdir("attach-p-cmd.test -p") = -1 ENOENT (No such file or directory)\n' $tracee_pid
+printf '%-5d +++ exited with 0 +++\n' $tracee_pid
+} >> "$OUT"
+
+match_diff "$LOG" "$OUT"
+rm -f "$OUT"