From eab4c772516af3365e6fcf82f6a48b4b94370b95 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Wed, 10 Jul 2019 16:12:44 +0000 Subject: [PATCH] Fix misleading stray PTRACE_EVENT_EXEC diagnostics If current_tcp is to be switched, entering(current_tcp) is irrelevant. * strace.c (maybe_switch_tcbs): Update comment. (dispatch_event) : Invoke maybe_switch_current_tcp early, skip the check for a stray PTRACE_EVENT_EXEC if current_tcp was switched. * tests/maybe_switch_current_tcp.c: New file. * tests/pure_executables.list: Add maybe_switch_current_tcp. * tests/.gitignore: Likewise. * tests/gen_tests.in (maybe_switch_current_tcp): New entry. * tests/Makefile.am (maybe_switch_current_tcp_LDADD): New variable. --- strace.c | 6 +-- tests/.gitignore | 1 + tests/Makefile.am | 1 + tests/gen_tests.in | 1 + tests/maybe_switch_current_tcp.c | 74 ++++++++++++++++++++++++++++++++ tests/pure_executables.list | 1 + 6 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 tests/maybe_switch_current_tcp.c diff --git a/strace.c b/strace.c index d4c1fa87..74c44253 100644 --- a/strace.c +++ b/strace.c @@ -2065,6 +2065,8 @@ maybe_switch_tcbs(struct tcb *tcp, const int pid) /* * One case we are here is -ff, try * "strace -oLOG -ff test/threaded_execve". + * Another case is demonstrated by + * tests/maybe_switch_current_tcp.c */ fprintf(execve_thread->outf, " \n", pid); /*execve_thread->curcol = 0; - no need, see code below */ @@ -2645,7 +2647,7 @@ dispatch_event(const struct tcb_wait_data *wd) * and all the following syscall state tracking is screwed up * otherwise. */ - if (entering(current_tcp)) { + if (!maybe_switch_current_tcp() && entering(current_tcp)) { int ret; error_msg("Stray PTRACE_EVENT_EXEC from pid %d" @@ -2662,8 +2664,6 @@ dispatch_event(const struct tcb_wait_data *wd) } } - maybe_switch_current_tcp(); - if (detach_on_execve) { if (current_tcp->flags & TCB_SKIP_DETACH_ON_FIRST_EXEC) { current_tcp->flags &= ~TCB_SKIP_DETACH_ON_FIRST_EXEC; diff --git a/tests/.gitignore b/tests/.gitignore index 59c71e00..caf26676 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -242,6 +242,7 @@ lseek lstat lstat64 madvise +maybe_switch_current_tcp mbind mbind-Xabbrev mbind-Xraw diff --git a/tests/Makefile.am b/tests/Makefile.am index a6b79d07..fc914d54 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -177,6 +177,7 @@ ftruncate64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 localtime_LDADD = $(clock_LIBS) $(LDADD) looping_threads_LDADD = -lpthread $(LDADD) lstat64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 +maybe_switch_current_tcp_LDADD = -lpthread $(LDADD) mmap64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 mmap64_Xabbrev_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 mmap64_Xraw_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64 diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 22e8c93a..d2d311ad 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -200,6 +200,7 @@ lookup_dcookie -a27 lstat -a32 -v -P stat.sample -P /dev/full lstat64 -a32 -v -P stat.sample -P /dev/full madvise -a33 +maybe_switch_current_tcp -a30 -f -e trace=execveat mbind mbind-Xabbrev -Xabbrev -e trace=mbind mbind-Xraw -a33 -Xraw -e trace=mbind diff --git a/tests/maybe_switch_current_tcp.c b/tests/maybe_switch_current_tcp.c new file mode 100644 index 00000000..bb3c266a --- /dev/null +++ b/tests/maybe_switch_current_tcp.c @@ -0,0 +1,74 @@ +/* + * Check for PTRACE_EVENT_EXEC diagnostics. + * + * Copyright (c) 2019 Dmitry V. Levin + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include +#include +#include +#include +#include +#include "scno.h" + +static pid_t leader; +static volatile unsigned int trigger; + +static void * +thread(void *arg) +{ + const char *argv[] = {((char **) arg)[0], "1", "2", NULL}; + int tid = syscall(__NR_gettid); + + printf("%-5d execveat(AT_FDCWD, \"%s\", [\"%s\", \"%s\", \"%s\"]" + ", NULL, 0 \n" + "%-5d +++ superseded by execve in pid %d +++\n", + tid, argv[0], argv[0], argv[1], argv[2], leader, + leader, tid); + + while (!trigger) { + /* Wait for the parent to enter the busy loop. */ + } + + syscall(__NR_execveat, -100, argv[0], argv, NULL, 0); + perror_msg_and_fail("execveat"); +} + +int +main(int ac, char **av) +{ + setvbuf(stdout, NULL, _IONBF, 0); + leader = getpid(); + + if (ac <= 1) { + char *argv[] = {av[0], (char *) "1", NULL}; + printf("%-5d execveat(AT_FDCWD, \"%s\"" + ", [\"%s\", \"%s\"], NULL, 0) = 0\n", + leader, argv[0], argv[0], argv[1]); + syscall(__NR_execveat, -100, argv[0], argv, NULL, 0); + perror_msg_and_skip("execveat"); + } + + /* + * Since execveat is supported by the kernel, + * PTRACE_EVENT_EXEC support in the kernel is good enough. + */ + if (ac <= 2) { + pthread_t t; + errno = pthread_create(&t, NULL, thread, av); + if (errno) + perror_msg_and_fail("pthread_create"); + + for (;;) + ++trigger; + } + + printf("%-5d <... execveat resumed>) = 0\n" + "%-5d +++ exited with 0 +++\n", + leader, leader); + return 0; +} diff --git a/tests/pure_executables.list b/tests/pure_executables.list index 58749797..96fad109 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -202,6 +202,7 @@ lseek lstat lstat64 madvise +maybe_switch_current_tcp mbind mbind-Xabbrev mbind-Xraw -- 2.40.0