]> granicus.if.org Git - strace/commitdiff
Fix misleading stray PTRACE_EVENT_EXEC diagnostics
authorDmitry V. Levin <ldv@altlinux.org>
Wed, 10 Jul 2019 16:12:44 +0000 (16:12 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 10 Jul 2019 16:12:44 +0000 (16:12 +0000)
If current_tcp is to be switched, entering(current_tcp) is irrelevant.

* strace.c (maybe_switch_tcbs): Update comment.
(dispatch_event) <case TE_STOP_BEFORE_EXECVE>: 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
tests/.gitignore
tests/Makefile.am
tests/gen_tests.in
tests/maybe_switch_current_tcp.c [new file with mode: 0644]
tests/pure_executables.list

index d4c1fa878bc89c28af3ad7392badd932c569c249..74c44253c178c45d2c952d7e4b988e8e6af10fb7 100644 (file)
--- 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, " <pid changed to %d ...>\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;
index 59c71e00a5999c4e1f69b2554b0dd18a411c5594..caf266763c0390968dc4537c925b93631a53e2ea 100644 (file)
@@ -242,6 +242,7 @@ lseek
 lstat
 lstat64
 madvise
+maybe_switch_current_tcp
 mbind
 mbind-Xabbrev
 mbind-Xraw
index a6b79d07cea5c60e6e2ca79c05d89b62c6e67532..fc914d5481094db3bf80fc8d301bc06f327c4b76 100644 (file)
@@ -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
index 22e8c93ae7a13f70103e0578d8187bef24f29374..d2d311ad97ba37c323552a3011a592fb7d7b03f8 100644 (file)
@@ -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 (file)
index 0000000..bb3c266
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Check for PTRACE_EVENT_EXEC diagnostics.
+ *
+ * Copyright (c) 2019 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "tests.h"
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <asm/unistd.h>
+#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 <pid changed to %d ...>\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;
+}
index 5874979707b4b6e6e708e22387588f51ca3ca758..96fad109f51f37d9d28336cf21f74052417f7392 100755 (executable)
@@ -202,6 +202,7 @@ lseek
 lstat
 lstat64
 madvise
+maybe_switch_current_tcp
 mbind
 mbind-Xabbrev
 mbind-Xraw