Implement simultaneous use of -p option and tracing of a command

* 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.
This commit is contained in:
Дмитрий Левин 2016-01-22 14:37:14 +00:00
parent 38721432de
commit fa8c286d50
8 changed files with 202 additions and 21 deletions

2
NEWS
View File

@ -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.

View File

@ -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

View File

@ -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
*/

2
tests/.gitignore vendored
View File

@ -8,6 +8,8 @@
_newselect
adjtimex
aio
attach-p-cmd-cmd
attach-p-cmd-p
bpf
caps
clock_nanosleep

View 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 \

44
tests/attach-p-cmd-cmd.c Normal file
View File

@ -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;
}

65
tests/attach-p-cmd-p.c Normal file
View File

@ -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;
}

54
tests/attach-p-cmd.test Executable file
View File

@ -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"