Move two global flags to tracee scope

A simultaneous use of -p option and tracing of a command available
since commit v4.11-183-gfa8c286 introduces a race condition because
the flags whether the first exec has happened are global.

Fix the race by moving hide_log_until_execve and hide_log_until_execve
global variables to TCB_HIDE_LOG and TCB_SKIP_DETACH_ON_FIRST_EXEC bits
in struct tcb.flags, correspondingly.

* defs.h (TCB_HIDE_LOG, TCB_SKIP_DETACH_ON_FIRST_EXEC, hide_log):
New macros.
(hide_log_until_execve): Remove prototype.
* strace.c (skip_one_b_execve, hide_log_until_execve): Remove.
(startup_child): Set TCB_HIDE_LOG and TCB_SKIP_DETACH_ON_FIRST_EXEC bits
in the allocated tcb structure.
(init): Remove initialization of hide_log_until_execve and
skip_one_b_execve.
(print_stopped): Use hide_log() instead of hide_log_until_execve.
(trace): Check and clear TCB_SKIP_DETACH_ON_FIRST_EXEC flag instead
of skip_one_b_execve.
* syscall.c (trace_syscall_entering): Clear TCB_HIDE_LOG flag instead of
hide_log_until_execve.
(trace_syscall_entering, trace_syscall_exiting): Check hide_log()
instead of hide_log_until_execve.
This commit is contained in:
Дмитрий Левин 2016-11-26 18:08:01 +00:00
parent 7910ac9638
commit 634a6a55e8
3 changed files with 19 additions and 21 deletions

4
defs.h
View File

@ -280,6 +280,8 @@ struct tcb {
#define TCB_REPRINT 0x10 /* We should reprint this syscall on exit */
#define TCB_FILTERED 0x20 /* This system call has been filtered out */
#define TCB_FAULT_INJ 0x40 /* A syscall fault has been injected */
#define TCB_HIDE_LOG 0x80 /* We should hide everything (until execve) */
#define TCB_SKIP_DETACH_ON_FIRST_EXEC 0x100 /* -b execve should skip detach on first execve */
/* qualifier flags */
#define QUAL_TRACE 0x001 /* this system call should be traced */
@ -300,6 +302,7 @@ typedef uint8_t qualbits_t;
#define verbose(tcp) ((tcp)->qual_flg & QUAL_VERBOSE)
#define abbrev(tcp) ((tcp)->qual_flg & QUAL_ABBREV)
#define filtered(tcp) ((tcp)->flags & TCB_FILTERED)
#define hide_log(tcp) ((tcp)->flags & TCB_HIDE_LOG)
#include "xlat.h"
@ -399,7 +402,6 @@ extern bool count_wallclock;
extern unsigned int qflag;
extern bool not_failing_only;
extern unsigned int show_fd_path;
extern bool hide_log_until_execve;
/* are we filtering traces based on paths? */
extern const char **paths_selected;
#define tracing_paths (paths_selected != NULL)

View File

@ -133,10 +133,6 @@ bool not_failing_only = 0;
unsigned int show_fd_path = 0;
static bool detach_on_execve = 0;
/* Are we "strace PROG" and need to skip detach on first execve? */
static bool skip_one_b_execve = 0;
/* Are we "strace PROG" and need to hide everything until execve? */
bool hide_log_until_execve = 0;
static int exit_code;
static int strace_child = 0;
@ -1418,17 +1414,17 @@ startup_child(char **argv)
kill(pid, SIGCONT);
}
tcp = alloctcb(pid);
if (!NOMMU_SYSTEM)
tcp->flags |= TCB_ATTACHED | TCB_STARTUP | post_attach_sigstop;
else
tcp->flags |= TCB_ATTACHED | TCB_STARTUP;
tcp->flags |= TCB_ATTACHED | TCB_STARTUP
| TCB_SKIP_DETACH_ON_FIRST_EXEC
| (NOMMU_SYSTEM ? 0 : (TCB_HIDE_LOG | post_attach_sigstop));
newoutf(tcp);
}
else {
/* With -D, we are *child* here, the tracee is our parent. */
strace_child = strace_tracer_pid;
strace_tracer_pid = getpid();
alloctcb(strace_child);
tcp = alloctcb(strace_child);
tcp->flags |= TCB_SKIP_DETACH_ON_FIRST_EXEC | TCB_HIDE_LOG;
/* attaching will be done later, by startup_attach */
/* note: we don't do newoutf(tcp) here either! */
@ -1859,9 +1855,6 @@ init(int argc, char *argv[])
* in the startup_child() mode we kill the spawned process anyway.
*/
if (argv[0]) {
if (!NOMMU_SYSTEM || daemonized_tracer)
hide_log_until_execve = 1;
skip_one_b_execve = 1;
startup_child(argv);
}
@ -2130,7 +2123,7 @@ static void
print_stopped(struct tcb *tcp, const siginfo_t *si, const unsigned int sig)
{
if (cflag != CFLAG_ONLY_STATS
&& !hide_log_until_execve
&& !hide_log(tcp)
&& (qual_flags[sig] & QUAL_SIGNAL)
) {
printleader(tcp);
@ -2266,11 +2259,14 @@ trace(void)
if (os_release >= KERNEL_VERSION(3,0,0))
tcp = maybe_switch_tcbs(tcp, pid);
if (detach_on_execve && !skip_one_b_execve) {
detach(tcp); /* do "-b execve" thingy */
return true;
if (detach_on_execve) {
if (tcp->flags & TCB_SKIP_DETACH_ON_FIRST_EXEC) {
tcp->flags &= ~TCB_SKIP_DETACH_ON_FIRST_EXEC;
} else {
detach(tcp); /* do "-b execve" thingy */
return true;
}
}
skip_one_b_execve = 0;
}
/* Set current output file */

View File

@ -1107,7 +1107,7 @@ trace_syscall_entering(struct tcb *tcp)
#if defined SPARC || defined SPARC64
case SEN_execv:
#endif
hide_log_until_execve = 0;
tcp->flags &= ~TCB_HIDE_LOG;
break;
}
@ -1121,7 +1121,7 @@ trace_syscall_entering(struct tcb *tcp)
tcp->flags &= ~TCB_FILTERED;
if (hide_log_until_execve) {
if (hide_log(tcp)) {
res = 0;
goto ret;
}
@ -1188,7 +1188,7 @@ trace_syscall_exiting(struct tcb *tcp)
update_personality(tcp, tcp->currpers);
#endif
res = (get_regs_error ? -1 : get_syscall_result(tcp));
if (filtered(tcp) || hide_log_until_execve)
if (filtered(tcp) || hide_log(tcp))
goto ret;
if (syserror(tcp) && syscall_fault_injected(tcp))