linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Bernd Edlinger <bernd.edlinger@hotmail.de>
To: Aleksa Sarai <cyphar@cyphar.com>
Cc: Jonathan Corbet <corbet@lwn.net>,
	Alexander Viro <viro@zeniv.linux.org.uk>,
	Andrew Morton <akpm@linux-foundation.org>,
	Alexey Dobriyan <adobriyan@gmail.com>,
	"Eric W. Biederman" <ebiederm@xmission.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Oleg Nesterov <oleg@redhat.com>,
	Frederic Weisbecker <frederic@kernel.org>,
	Andrei Vagin <avagin@gmail.com>, Ingo Molnar <mingo@kernel.org>,
	"Peter Zijlstra (Intel)" <peterz@infradead.org>,
	Yuyang Du <duyuyang@gmail.com>,
	David Hildenbrand <david@redhat.com>,
	Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
	Anshuman Khandual <anshuman.khandual@arm.com>,
	David Howells <dhowells@redhat.com>, Jann Horn <jannh@google.com>,
	James Morris <jamorris@linux.microsoft.com>,
	Kees Cook <keescook@chromium.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Shakeel Butt <shakeelb@google.com>,
	Christian Brauner <christian.brauner@ubuntu.com>,
	Jason Gunthorpe <jgg@ziepe.ca>,
	Christian Kellner <christian@kellner.me>,
	Andrea Arcangeli <aarcange@redhat.com>,
	"Dmitry V. Levin" <ldv@altlinux.org>,
	"linux-doc@vger.kernel.org" <linux-doc@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"linux-fsdevel@vger.kernel.org" <linux-fsdevel@vger.kernel.org>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>
Subject: Re: [PATCH] exec: Fix a deadlock in ptrace
Date: Sun, 1 Mar 2020 17:24:47 +0000	[thread overview]
Message-ID: <AM6PR03MB5170D68B5010FCA627A603F8E4E60@AM6PR03MB5170.eurprd03.prod.outlook.com> (raw)
In-Reply-To: <20200301151333.bsjfdjcjddsza2vn@yavin>

[-- Attachment #1: Type: text/plain, Size: 4335 bytes --]

Hi Aleksa,

On 3/1/20 4:13 PM, Aleksa Sarai wrote:
> On 2020-03-01, Bernd Edlinger <bernd.edlinger@hotmail.de> wrote:
>> This fixes a deadlock in the tracer when tracing a multi-threaded
>> application that calls execve while more than one thread are running.
>>
>> I observed that when running strace on the gcc test suite, it always
>> blocks after a while, when expect calls execve, because other threads
>> have to be terminated.  They send ptrace events, but the strace is no
>> longer able to respond, since it is blocked in vm_access.
>>
>> The deadlock is always happening when strace needs to access the
>> tracees process mmap, while another thread in the tracee starts to
>> execve a child process, but that cannot continue until the
>> PTRACE_EVENT_EXIT is handled and the WIFEXITED event is received:
>>
>> strace          D    0 30614  30584 0x00000000
>> Call Trace:
>> __schedule+0x3ce/0x6e0
>> schedule+0x5c/0xd0
>> schedule_preempt_disabled+0x15/0x20
>> __mutex_lock.isra.13+0x1ec/0x520
>> __mutex_lock_killable_slowpath+0x13/0x20
>> mutex_lock_killable+0x28/0x30
>> mm_access+0x27/0xa0
>> process_vm_rw_core.isra.3+0xff/0x550
>> process_vm_rw+0xdd/0xf0
>> __x64_sys_process_vm_readv+0x31/0x40
>> do_syscall_64+0x64/0x220
>> entry_SYSCALL_64_after_hwframe+0x44/0xa9
>>
>> expect          D    0 31933  30876 0x80004003
>> Call Trace:
>> __schedule+0x3ce/0x6e0
>> schedule+0x5c/0xd0
>> flush_old_exec+0xc4/0x770
>> load_elf_binary+0x35a/0x16c0
>> search_binary_handler+0x97/0x1d0
>> __do_execve_file.isra.40+0x5d4/0x8a0
>> __x64_sys_execve+0x49/0x60
>> do_syscall_64+0x64/0x220
>> entry_SYSCALL_64_after_hwframe+0x44/0xa9
>>
>> The proposed solution is to have a second mutex that is
>> used in mm_access, so it is allowed to continue while the
>> dying threads are not yet terminated.
>>
>> I also took the opportunity to improve the documentation
>> of prepare_creds, which is obviously out of sync.
>>
>> Signed-off-by: Bernd Edlinger <bernd.edlinger@hotmail.de>
> 
> I can't comment on the validity of the patch, but I also found and
> reported this issue in 2016[1] and the discussion quickly veered into
> the problem being more complicated (and uglier) than it seems at first
> glance.
> 
> You should probably also Cc stable, given this has been a long-standing
> issue and your patch doesn't look (too) invasive.
> 

I am fully aware that this patch won't fix the case then PTRACE_ACCESS is racing
with de_thread.  But I don't see a problem with allowing vm access based on the
current credentials as they are still the same until de_thread is done with it's
job.  And in a practical way this fixes 99% of the real problem here, as it only
happens since strace is currently tracing something and needs access to the parameters
in the tracee's vm space.
Of course you could fork the strace process to do any PTRACE_ACCESS when necessary,
and, well, maybe that would fix the remaining problem here...

However before I considered changing the kernel for this I tried to fix this
within strace.  First I tried to wait in the signal handler.  See attached
strace-patch-1.diff, but that did not work, BUT I think it is possible that your
patch you proposed previously would actually make it work.

I tried then another approach, using a worker thread to wait for the childs,
but it did only work when I remove PTRACE_O_TRACEEXIT from the ptrace options,
because the ptrace(PTRACE_SYSCALL, pid, 0L, 0L) does not work in the worker thread,
rv = -1, errno = 3 there, and unfortunately the main thread is blocked and unable
to do the ptrace call, that makes the thread continue.
So I consider that second patch really ugly, and wouldn't propose something like
that seriously.


@@ -69,7 +71,7 @@
 cflag_t cflag = CFLAG_NONE;
 unsigned int followfork;
 unsigned int ptrace_setoptions = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC
-                                | PTRACE_O_TRACEEXIT;
+                                ;//| PTRACE_O_TRACEEXIT;
 unsigned int xflag;
 bool debug_flag;
 bool Tflag;

so it only works because of this line, without that it is not able to make the
thread continue after the PTRACE_EVENT_EXIT. 


Thanks
Bernd.

> [1]: https://lore.kernel.org/lkml/20160921152946.GA24210@dhcp22.suse.cz/
> 

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: strace-patch-1.diff --]
[-- Type: text/x-patch; name="strace-patch-1.diff", Size: 7652 bytes --]

diff -ur strace-5.5/delay.h strace-5.5.x/delay.h
--- strace-5.5/delay.h	2019-08-06 15:38:20.000000000 +0200
+++ strace-5.5.x/delay.h	2020-02-29 12:39:51.563110827 +0100
@@ -14,5 +14,6 @@
 void delay_timer_expired(void);
 void arm_delay_timer(const struct tcb *);
 void delay_tcb(struct tcb *, uint16_t delay_idx, bool isenter);
+int my_waitpid(int, int*, int);
 
 #endif /* !STRACE_DELAY_H */
diff -ur strace-5.5/filter_seccomp.c strace-5.5.x/filter_seccomp.c
--- strace-5.5/filter_seccomp.c	2020-02-06 16:16:17.000000000 +0100
+++ strace-5.5.x/filter_seccomp.c	2020-02-29 12:42:43.184120263 +0100
@@ -19,6 +19,7 @@
 #include "number_set.h"
 #include "syscall.h"
 #include "scno.h"
+#include "delay.h"
 
 bool seccomp_filtering;
 bool seccomp_before_sysentry;
@@ -136,7 +137,7 @@
 		int status;
 
 		for (;;) {
-			long rc = waitpid(pid, &status, 0);
+			long rc = my_waitpid(pid, &status, 0);
 			if (rc < 0 && errno == EINTR)
 				continue;
 			if (rc == pid)
@@ -272,7 +273,7 @@
 	if (pid) {
 		kill(pid, SIGKILL);
 		for (;;) {
-			long rc = waitpid(pid, NULL, 0);
+			long rc = my_waitpid(pid, NULL, 0);
 			if (rc < 0 && errno == EINTR)
 				continue;
 			break;
diff -ur strace-5.5/Makefile.am strace-5.5.x/Makefile.am
--- strace-5.5/Makefile.am	2020-02-06 16:16:17.000000000 +0100
+++ strace-5.5.x/Makefile.am	2020-02-29 10:28:04.515676065 +0100
@@ -45,7 +45,7 @@
 strace_CPPFLAGS = $(AM_CPPFLAGS)
 strace_CFLAGS = $(AM_CFLAGS)
 strace_LDFLAGS =
-strace_LDADD = libstrace.a $(clock_LIBS) $(timer_LIBS)
+strace_LDADD = libstrace.a -lpthread $(clock_LIBS) $(timer_LIBS)
 noinst_LIBRARIES = libstrace.a
 
 libstrace_a_CPPFLAGS = $(strace_CPPFLAGS)
diff -ur strace-5.5/Makefile.in strace-5.5.x/Makefile.in
--- strace-5.5/Makefile.in	2020-02-06 17:23:35.000000000 +0100
+++ strace-5.5.x/Makefile.in	2020-02-29 10:28:28.833677402 +0100
@@ -1631,7 +1631,7 @@
 	$(am__append_11) $(CODE_COVERAGE_CPPFLAGS)
 strace_CFLAGS = $(AM_CFLAGS) $(am__append_4) $(CODE_COVERAGE_CFLAGS)
 strace_LDFLAGS = $(am__append_5) $(am__append_9) $(am__append_12)
-strace_LDADD = libstrace.a $(clock_LIBS) $(timer_LIBS) $(am__append_6) \
+strace_LDADD = libstrace.a -lpthread $(clock_LIBS) $(timer_LIBS) $(am__append_6) \
 	$(am__append_10) $(am__append_13) $(CODE_COVERAGE_LIBS) \
 	$(am__append_14) $(am__append_18)
 noinst_LIBRARIES = libstrace.a $(am__append_15) $(am__append_19)
diff -ur strace-5.5/ptrace_syscall_info.c strace-5.5.x/ptrace_syscall_info.c
--- strace-5.5/ptrace_syscall_info.c	2020-02-06 16:16:17.000000000 +0100
+++ strace-5.5.x/ptrace_syscall_info.c	2020-02-29 12:41:44.565117040 +0100
@@ -12,6 +12,7 @@
 #include "ptrace.h"
 #include "ptrace_syscall_info.h"
 #include "scno.h"
+#include "delay.h"
 
 #include <signal.h>
 #include <sys/wait.h>
@@ -118,7 +119,7 @@
 		};
 		const size_t size = sizeof(info);
 		int status;
-		long rc = waitpid(pid, &status, 0);
+		long rc = my_waitpid(pid, &status, 0);
 		if (rc != pid) {
 			/* cannot happen */
 			kill_tracee(pid);
@@ -247,7 +248,7 @@
 done:
 	if (pid) {
 		kill_tracee(pid);
-		waitpid(pid, NULL, 0);
+		my_waitpid(pid, NULL, 0);
 		ptrace_stop = -1U;
 	}
 
diff -ur strace-5.5/strace.c strace-5.5.x/strace.c
--- strace-5.5/strace.c	2020-02-06 16:16:17.000000000 +0100
+++ strace-5.5.x/strace.c	2020-03-01 07:53:27.028407698 +0100
@@ -15,6 +15,7 @@
 #include <fcntl.h>
 #include "ptrace.h"
 #include <signal.h>
+#include <semaphore.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
 #ifdef HAVE_PATHS_H
@@ -1002,7 +1003,7 @@
 	 */
 	for (;;) {
 		unsigned int sig;
-		if (waitpid(tcp->pid, &status, __WALL) < 0) {
+		if (my_waitpid(tcp->pid, &status, __WALL) < 0) {
 			if (errno == EINTR)
 				continue;
 			/*
@@ -1615,7 +1616,7 @@
 		int status, tracee_pid;
 
 		errno = 0;
-		tracee_pid = waitpid(pid, &status, 0);
+		tracee_pid = my_waitpid(pid, &status, 0);
 		if (tracee_pid <= 0) {
 			if (errno == EINTR)
 				continue;
@@ -1663,6 +1664,69 @@
 	sigaction(signo, &sa, oldact);
 }
 
+#define MAX_WAITIDX 65536
+static unsigned short in_idx = 0, out_idx = 0;
+static sem_t wait_sem;
+static int wait_pid[MAX_WAITIDX];
+static int wait_status[MAX_WAITIDX];
+static struct rusage wait_rusage[MAX_WAITIDX];
+
+static void
+child_sighandler(int sig)
+{
+	int old_errno = errno;
+	int status;
+	struct rusage ru;
+	int pid = wait4(-1, &status, __WALL | WNOHANG, (cflag ? &ru : NULL));
+
+	if (pid > 0) {
+		if (WIFSTOPPED(status) && (status >> 16) == PTRACE_EVENT_EXIT)
+			ptrace(PTRACE_SYSCALL, pid, 0L, 0L);
+		wait_pid[in_idx] = pid;
+		wait_status[in_idx] = status;
+		if (cflag)
+			wait_rusage[in_idx] = ru;
+		in_idx++;
+		if (in_idx == out_idx || sem_post(&wait_sem) == -1)
+		{
+			const char *msg = "fatal error in child_sighandler\n"; 
+			status = write(STDERR_FILENO, msg, strlen(msg));
+			_exit(2);
+		}
+	}
+
+	errno = old_errno; 
+}
+
+int my_waitpid(int pid, int *status, int options)
+{
+	int skip = 0;
+	unsigned short idx = out_idx;
+	for (;;) {
+		while (sem_wait(&wait_sem) == -1 && errno == EINTR)
+			;
+		if (wait_pid[idx] == pid)
+			break;
+		idx++;
+		skip++;
+	}
+	*status = wait_status[idx];
+	while (skip > 0) {
+		unsigned short idx1 = idx;
+		idx1--;
+		wait_status[idx] = wait_status[idx1];
+		wait_pid[idx] = wait_pid[idx1];
+		if (cflag)
+			wait_rusage[idx] = wait_rusage[idx1];
+		if (sem_post(&wait_sem) == -1)
+			error_msg_and_die("fatal error in my_waitpid"); 
+		skip--;
+		idx--;
+	}
+	out_idx++;
+	return pid;
+}
+
 /*
  * Initialization part of main() was eating much stack (~0.5k),
  * which was unused after init.
@@ -2015,7 +2079,9 @@
 	memset(acolumn_spaces, ' ', acolumn);
 	acolumn_spaces[acolumn] = '\0';
 
-	set_sighandler(SIGCHLD, SIG_DFL, &params_for_tracee.child_sa);
+	if (sem_init(&wait_sem, 0, 0) == -1)
+		perror_msg_and_die("Unable to initialize signal wait sema");
+	set_sighandler(SIGCHLD, child_sighandler, &params_for_tracee.child_sa);
 
 #ifdef ENABLE_STACKTRACE
 	if (stack_trace_enabled)
@@ -2607,10 +2673,28 @@
 	 * then the system call will be interrupted and
 	 * the expiration will be handled by the signal handler.
 	 */
-	int status;
+	int status = 0;
 	struct rusage ru;
-	int pid = wait4(-1, &status, __WALL, (cflag ? &ru : NULL));
-	int wait_errno = errno;
+	int pid = 0;
+	int wait_errno = 0;
+	if (in_idx == out_idx) {
+		pid = wait4(-1, &status, __WALL | WNOHANG, (cflag ? &ru : NULL));
+		wait_errno = errno;
+		if (pid > 0 && WIFSTOPPED(status) && (status >> 16) == PTRACE_EVENT_EXIT)
+			ptrace(PTRACE_SYSCALL, pid, 0L, 0L);
+	}
+	if (pid == 0) {
+		while (sem_wait(&wait_sem) == -1 && errno == EINTR)
+			;
+
+		if (in_idx == out_idx)
+			error_msg_and_die("wait queue error");
+		pid = wait_pid[out_idx];
+		status = wait_status[out_idx];
+		if (cflag)
+			ru = wait_rusage[out_idx];
+		out_idx++;
+	}
 
 	/*
 	 * The window of opportunity to handle expirations
@@ -2791,8 +2875,17 @@
 			break;
 
 next_event_wait_next:
-		pid = wait4(-1, &status, __WALL | WNOHANG, (cflag ? &ru : NULL));
-		wait_errno = errno;
+		pid = 0;
+		if (in_idx != out_idx) {
+			while (sem_wait(&wait_sem) == -1 && errno == EINTR)
+				;
+
+			pid = wait_pid[out_idx];
+			status = wait_status[out_idx];
+			if (cflag)
+				ru = wait_rusage[out_idx];
+			out_idx++;
+		}
 		wait_nohang = true;
 	}
 
@@ -3019,7 +3112,7 @@
 
 	case TE_STOP_BEFORE_EXIT:
 		print_event_exit(current_tcp);
-		break;
+		return true;
 	}
 
 	/* We handled quick cases, we are permitted to interrupt now. */
@@ -3138,7 +3231,7 @@
 	if (shared_log != stderr)
 		fclose(shared_log);
 	if (popen_pid) {
-		while (waitpid(popen_pid, NULL, 0) < 0 && errno == EINTR)
+		while (my_waitpid(popen_pid, NULL, 0) < 0 && errno == EINTR)
 			;
 	}
 	if (sig) {

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: strace-patch-2.diff --]
[-- Type: text/x-patch; name="strace-patch-2.diff", Size: 7878 bytes --]

diff -ur strace-5.5/delay.h strace-5.5.y/delay.h
--- strace-5.5/delay.h	2019-08-06 15:38:20.000000000 +0200
+++ strace-5.5.y/delay.h	2020-02-29 12:39:51.563110827 +0100
@@ -14,5 +14,6 @@
 void delay_timer_expired(void);
 void arm_delay_timer(const struct tcb *);
 void delay_tcb(struct tcb *, uint16_t delay_idx, bool isenter);
+int my_waitpid(int, int*, int);
 
 #endif /* !STRACE_DELAY_H */
diff -ur strace-5.5/filter_seccomp.c strace-5.5.y/filter_seccomp.c
--- strace-5.5/filter_seccomp.c	2020-02-06 16:16:17.000000000 +0100
+++ strace-5.5.y/filter_seccomp.c	2020-02-29 12:42:43.184120263 +0100
@@ -19,6 +19,7 @@
 #include "number_set.h"
 #include "syscall.h"
 #include "scno.h"
+#include "delay.h"
 
 bool seccomp_filtering;
 bool seccomp_before_sysentry;
@@ -136,7 +137,7 @@
 		int status;
 
 		for (;;) {
-			long rc = waitpid(pid, &status, 0);
+			long rc = my_waitpid(pid, &status, 0);
 			if (rc < 0 && errno == EINTR)
 				continue;
 			if (rc == pid)
@@ -272,7 +273,7 @@
 	if (pid) {
 		kill(pid, SIGKILL);
 		for (;;) {
-			long rc = waitpid(pid, NULL, 0);
+			long rc = my_waitpid(pid, NULL, 0);
 			if (rc < 0 && errno == EINTR)
 				continue;
 			break;
diff -ur strace-5.5/Makefile.am strace-5.5.y/Makefile.am
--- strace-5.5/Makefile.am	2020-02-06 16:16:17.000000000 +0100
+++ strace-5.5.y/Makefile.am	2020-02-29 10:28:04.515676065 +0100
@@ -45,7 +45,7 @@
 strace_CPPFLAGS = $(AM_CPPFLAGS)
 strace_CFLAGS = $(AM_CFLAGS)
 strace_LDFLAGS =
-strace_LDADD = libstrace.a $(clock_LIBS) $(timer_LIBS)
+strace_LDADD = libstrace.a -lpthread $(clock_LIBS) $(timer_LIBS)
 noinst_LIBRARIES = libstrace.a
 
 libstrace_a_CPPFLAGS = $(strace_CPPFLAGS)
diff -ur strace-5.5/Makefile.in strace-5.5.y/Makefile.in
--- strace-5.5/Makefile.in	2020-02-06 17:23:35.000000000 +0100
+++ strace-5.5.y/Makefile.in	2020-02-29 10:28:28.833677402 +0100
@@ -1631,7 +1631,7 @@
 	$(am__append_11) $(CODE_COVERAGE_CPPFLAGS)
 strace_CFLAGS = $(AM_CFLAGS) $(am__append_4) $(CODE_COVERAGE_CFLAGS)
 strace_LDFLAGS = $(am__append_5) $(am__append_9) $(am__append_12)
-strace_LDADD = libstrace.a $(clock_LIBS) $(timer_LIBS) $(am__append_6) \
+strace_LDADD = libstrace.a -lpthread $(clock_LIBS) $(timer_LIBS) $(am__append_6) \
 	$(am__append_10) $(am__append_13) $(CODE_COVERAGE_LIBS) \
 	$(am__append_14) $(am__append_18)
 noinst_LIBRARIES = libstrace.a $(am__append_15) $(am__append_19)
diff -ur strace-5.5/strace.c strace-5.5.y/strace.c
--- strace-5.5/strace.c	2020-02-06 16:16:17.000000000 +0100
+++ strace-5.5.y/strace.c	2020-03-01 07:59:55.586429063 +0100
@@ -15,6 +15,8 @@
 #include <fcntl.h>
 #include "ptrace.h"
 #include <signal.h>
+#include <semaphore.h>
+#include <pthread.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
 #ifdef HAVE_PATHS_H
@@ -69,7 +71,7 @@
 cflag_t cflag = CFLAG_NONE;
 unsigned int followfork;
 unsigned int ptrace_setoptions = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC
-				 | PTRACE_O_TRACEEXIT;
+				 ;//| PTRACE_O_TRACEEXIT;
 unsigned int xflag;
 bool debug_flag;
 bool Tflag;
@@ -1002,7 +1004,7 @@
 	 */
 	for (;;) {
 		unsigned int sig;
-		if (waitpid(tcp->pid, &status, __WALL) < 0) {
+		if (my_waitpid(tcp->pid, &status, __WALL) < 0) {
 			if (errno == EINTR)
 				continue;
 			/*
@@ -1663,6 +1665,83 @@
 	sigaction(signo, &sa, oldact);
 }
 
+#define MAX_WAITIDX 65536
+static unsigned short in_idx = 0, out_idx = 0;
+static sem_t wait_sem;
+static pthread_t wait_thread;
+static int wait_pid[MAX_WAITIDX];
+static int wait_status[MAX_WAITIDX];
+static struct rusage wait_rusage[MAX_WAITIDX];
+
+static void*
+child_sighandler(void *arg)
+{
+	int status;
+	struct rusage ru;
+	int pid;
+	for (;;) {
+		pid = wait4(-1, &status, __WALL, (cflag ? &ru : NULL));
+		if (pid < 0 && errno == EINTR)
+			continue;
+
+		if (pid < 0)
+			pid = -errno;
+
+		if (pid > 0 && WIFSTOPPED(status) && (status >> 16) == PTRACE_EVENT_EXIT) {
+			int i = ptrace(PTRACE_SYSCALL, pid, 0L, 0L);
+			fprintf(stderr, "in thread: ptrace(PTRACE_SYSCALL, %d, 0L, 0L)=%d errno=%d\n", pid, i, errno);
+		}
+		wait_pid[in_idx] = pid;
+		wait_status[in_idx] = status;
+		if (cflag)
+			wait_rusage[in_idx] = ru;
+		in_idx++;
+		if (in_idx == out_idx || sem_post(&wait_sem) == -1)
+			error_msg_and_die("fatal error in child_sighandler"); 
+		if (pid < 0)
+			break;
+	}
+
+	return NULL;
+}
+
+int my_waitpid(int pid, int *status, int options)
+{
+	int skip = 0;
+	unsigned short idx = out_idx;
+	for (;;) {
+		while (sem_wait(&wait_sem) == -1 && errno == EINTR)
+			;
+		if (wait_pid[idx] < 0) {
+			while (skip-- >= 0)
+				sem_post(&wait_sem);
+			errno = -wait_pid[idx];
+			return -1;
+		}
+		if (wait_pid[idx] == pid)
+			break;
+		idx++;
+		skip++;
+	}
+	*status = wait_status[idx];
+	while (skip > 0) {
+		unsigned short idx1 = idx;
+		idx1--;
+		wait_status[idx] = wait_status[idx1];
+		wait_pid[idx] = wait_pid[idx1];
+		if (cflag)
+			wait_rusage[idx] = wait_rusage[idx1];
+		if (sem_post(&wait_sem) == -1)
+			error_msg_and_die("fatal error in my_waitpid"); 
+		skip--;
+		idx--;
+	}
+	out_idx++;
+	if (pid < 0)
+		errno = -pid;
+	return pid < 0 ? -1 : pid;
+}
+
 /*
  * Initialization part of main() was eating much stack (~0.5k),
  * which was unused after init.
@@ -2124,6 +2203,9 @@
 		startup_child(argv);
 	}
 
+	if (sem_init(&wait_sem, 0, 0) == -1)
+		perror_msg_and_die("Unable to initialize signal wait sema");
+
 	set_sighandler(SIGTTOU, SIG_IGN, NULL);
 	set_sighandler(SIGTTIN, SIG_IGN, NULL);
 	if (opt_intr != INTR_ANYWHERE) {
@@ -2150,6 +2232,7 @@
 	if (nprocs != 0 || daemonized_tracer)
 		startup_attach();
 
+	pthread_create(&wait_thread, NULL, child_sighandler, NULL);
 	/* Do we want pids printed in our -o OUTFILE?
 	 * -ff: no (every pid has its own file); or
 	 * -f: yes (there can be more pids in the future); or
@@ -2607,10 +2690,28 @@
 	 * then the system call will be interrupted and
 	 * the expiration will be handled by the signal handler.
 	 */
-	int status;
+	int status = 0;
 	struct rusage ru;
-	int pid = wait4(-1, &status, __WALL, (cflag ? &ru : NULL));
-	int wait_errno = errno;
+	int pid = 0;
+	int wait_errno = 0;
+	while (sem_wait(&wait_sem) == -1 && errno == EINTR)
+		;
+
+	if (in_idx == out_idx)
+		error_msg_and_die("wait queue error");
+	pid = wait_pid[out_idx];
+	status = wait_status[out_idx];
+	ru = wait_rusage[out_idx];
+	if (pid > 0 && WIFSTOPPED(status) && (status >> 16) == PTRACE_EVENT_EXIT) {
+		int i = ptrace(PTRACE_SYSCALL, pid, 0L, 0L);
+		fprintf(stderr, "ptrace(PTRACE_SYSCALL, %d, 0L, 0L)=%d errno=%d\n", pid, i, errno);
+	}
+	out_idx++;
+	if (pid < 0) {
+		wait_errno = -pid;
+		out_idx--;
+		sem_post(&wait_sem);
+	}
 
 	/*
 	 * The window of opportunity to handle expirations
@@ -2791,8 +2892,25 @@
 			break;
 
 next_event_wait_next:
-		pid = wait4(-1, &status, __WALL | WNOHANG, (cflag ? &ru : NULL));
-		wait_errno = errno;
+		pid = 0;
+		if (in_idx != out_idx) {
+			while (sem_wait(&wait_sem) == -1 && errno == EINTR)
+				;
+
+			pid = wait_pid[out_idx];
+			status = wait_status[out_idx];
+			ru = wait_rusage[out_idx];
+			if (pid > 0 && WIFSTOPPED(status) && (status >> 16) == PTRACE_EVENT_EXIT) {
+				int i = ptrace(PTRACE_SYSCALL, pid, 0L, 0L);
+				fprintf(stderr, "ptrace(PTRACE_SYSCALL, %d, 0L, 0L)=%d errno=%d\n", pid, i, errno);
+			}
+			out_idx++;
+			if (pid < 0) {
+				wait_errno = -pid;
+				out_idx--;
+				sem_post(&wait_sem);
+			}
+		}
 		wait_nohang = true;
 	}
 
@@ -3019,7 +3137,8 @@
 
 	case TE_STOP_BEFORE_EXIT:
 		print_event_exit(current_tcp);
-		break;
+		//droptcb(current_tcp);
+		return true;
 	}
 
 	/* We handled quick cases, we are permitted to interrupt now. */
@@ -3138,9 +3257,10 @@
 	if (shared_log != stderr)
 		fclose(shared_log);
 	if (popen_pid) {
-		while (waitpid(popen_pid, NULL, 0) < 0 && errno == EINTR)
+		while (my_waitpid(popen_pid, NULL, 0) < 0 && errno == EINTR)
 			;
 	}
+	pthread_join(wait_thread, NULL);
 	if (sig) {
 		exit_code = 0x100 | sig;
 	}

  parent reply	other threads:[~2020-03-01 17:28 UTC|newest]

Thread overview: 203+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-01 11:27 [PATCH] exec: Fix a deadlock in ptrace Bernd Edlinger
2020-03-01 15:13 ` Aleksa Sarai
2020-03-01 15:58   ` Christian Brauner
2020-03-01 17:46     ` Bernd Edlinger
2020-03-01 18:20       ` Christian Brauner
2020-03-01 17:24   ` Bernd Edlinger [this message]
2020-03-01 18:21 ` Jann Horn
2020-03-01 18:52   ` Christian Brauner
2020-03-01 19:00     ` Bernd Edlinger
2020-03-01 20:00     ` Jann Horn
2020-03-01 20:34       ` [PATCHv2] " Bernd Edlinger
2020-03-02  6:38         ` Eric W. Biederman
2020-03-02 15:43           ` Bernd Edlinger
2020-03-02 15:57             ` Eric W. Biederman
2020-03-02 16:02               ` Bernd Edlinger
2020-03-02 16:17                 ` Eric W. Biederman
2020-03-02 16:43                   ` Jann Horn
2020-03-02 17:01                     ` Bernd Edlinger
2020-03-02 17:37                       ` Jann Horn
2020-03-02 17:42                         ` christian
2020-03-02 18:08                           ` Jann Horn
2020-03-02 20:10                             ` [PATCHv3] " Bernd Edlinger
2020-03-02 20:28                               ` Bernd Edlinger
2020-03-02 17:13                   ` [PATCHv2] " Bernd Edlinger
2020-03-02 21:49                     ` Eric W. Biederman
2020-03-02 22:00                       ` Bernd Edlinger
2020-03-02 22:18                       ` [PATCHv4] " Bernd Edlinger
2020-03-03  2:26                         ` Kees Cook
2020-03-03  4:54                           ` Bernd Edlinger
2020-03-03  5:29                             ` Kees Cook
2020-03-03  8:08                               ` Bernd Edlinger
2020-03-03  8:34                                 ` Christian Brauner
2020-03-03  8:43                                   ` Christian Brauner
2020-03-04 15:30                                 ` Christian Brauner
2020-03-03  8:58                           ` Christian Brauner
2020-03-03 10:34                             ` Bernd Edlinger
2020-03-03 11:23                               ` Bernd Edlinger
2020-03-03 14:20                                 ` Christian Brauner
2020-03-03 13:02                             ` [PATCHv5] " Bernd Edlinger
2020-03-03 15:18                               ` Eric W. Biederman
2020-03-03 16:48                                 ` Bernd Edlinger
2020-03-03 17:01                                   ` Christian Brauner
2020-03-03 17:20                                     ` Christian Brauner
2020-03-03 20:08                                   ` Eric W. Biederman
2020-03-04 14:37                                     ` Bernd Edlinger
2020-03-04 16:33                                       ` Eric W. Biederman
2020-03-04 21:49                                         ` Bernd Edlinger
2020-03-04 21:56                                         ` [PATCHv6] " Bernd Edlinger
2020-03-05 18:36                                           ` Bernd Edlinger
2020-03-05 21:14                                             ` [PATCH 0/2] Infrastructure to allow fixing exec deadlocks Eric W. Biederman
2020-03-05 21:15                                               ` [PATCH 1/2] exec: Properly mark the point of no return Eric W. Biederman
2020-03-05 22:34                                                 ` Bernd Edlinger
2020-03-06  5:19                                                   ` Eric W. Biederman
2020-03-05 22:56                                                 ` Bernd Edlinger
2020-03-06  5:09                                                   ` Eric W. Biederman
2020-03-06 16:26                                                     ` Bernd Edlinger
2020-03-06 17:16                                                       ` Eric W. Biederman
2020-03-05 21:16                                               ` [PATCH 2/2] exec: Add a exec_update_mutex to replace cred_guard_mutex Eric W. Biederman
2020-03-05 21:51                                                 ` Bernd Edlinger
2020-03-06  5:17                                                   ` Eric W. Biederman
2020-03-06 11:46                                                     ` Bernd Edlinger
2020-03-06 21:18                                                       ` Eric W. Biederman
2020-03-06 19:16                                                     ` Bernd Edlinger
2020-03-06 21:58                                                       ` Eric W. Biederman
2020-03-06 22:29                                                         ` Eric W. Biederman
2020-03-07  1:03                                                           ` Eric W. Biederman
2020-03-08 12:58                                                             ` [PATCH] exec: make de_thread alloc new signal struct earlier Bernd Edlinger
2020-03-08 18:12                                                               ` Eric W. Biederman
2020-03-05 22:31                                               ` [PATCH 0/2] Infrastructure to allow fixing exec deadlocks Bernd Edlinger
2020-03-06  5:06                                                 ` Eric W. Biederman
2020-03-08 21:34                                               ` [PATCH 0/5] " Eric W. Biederman
2020-03-08 21:35                                                 ` [PATCH v2 1/5] exec: Only compute current once in flush_old_exec Eric W. Biederman
2020-03-09 13:56                                                   ` Bernd Edlinger
2020-03-09 17:34                                                     ` Eric W. Biederman
2020-03-09 17:56                                                       ` Bernd Edlinger
2020-03-09 19:27                                                         ` Bernd Edlinger
2020-03-10 20:17                                                   ` Kees Cook
2020-03-10 21:12                                                   ` Christian Brauner
2020-03-08 21:36                                                 ` [PATCH v2 2/5] exec: Factor unshare_sighand out of de_thread and call it separately Eric W. Biederman
2020-03-09 19:28                                                   ` Bernd Edlinger
2020-03-10 20:29                                                   ` Kees Cook
2020-03-10 20:34                                                     ` Bernd Edlinger
2020-03-10 20:57                                                       ` Kees Cook
2020-03-10 21:21                                                   ` Christian Brauner
2020-03-08 21:36                                                 ` [PATCH v2 3/5] exec: Move cleanup of posix timers on exec out of de_thread Eric W. Biederman
2020-03-09 19:30                                                   ` Bernd Edlinger
2020-03-09 19:59                                                   ` Christian Brauner
2020-03-09 20:06                                                     ` Eric W. Biederman
2020-03-09 20:17                                                       ` Christian Brauner
2020-03-09 20:48                                                         ` Eric W. Biederman
2020-03-10  8:55                                                           ` Christian Brauner
2020-03-10 18:52                                                             ` [PATCH] pidfd: Stop taking cred_guard_mutex Eric W. Biederman
2020-03-10 19:15                                                               ` Christian Brauner
2020-03-10 19:16                                                               ` Jann Horn
2020-03-10 19:27                                                                 ` Eric W. Biederman
2020-03-10 20:00                                                                   ` Jann Horn
2020-03-10 20:10                                                                     ` Jann Horn
2020-03-10 20:22                                                                       ` Bernd Edlinger
2020-03-11  6:11                                                                         ` Bernd Edlinger
2020-03-11 14:56                                                                           ` Jann Horn
2020-03-10 20:57                                                                       ` Eric W. Biederman
2020-03-10 21:29                                                                         ` Christian Brauner
2020-03-11 18:49                                                                         ` Kees Cook
2020-03-14  9:12                                                                           ` [PATCH] pidfd: Use new infrastructure to fix deadlocks in execve Bernd Edlinger
2020-03-10 20:16                                                           ` [PATCH v2 3/5] exec: Move cleanup of posix timers on exec out of de_thread Kees Cook
2020-03-10 20:31                                                   ` Kees Cook
2020-03-10 20:57                                                   ` Jann Horn
2020-03-10 21:05                                                     ` Eric W. Biederman
2020-03-10 21:22                                                   ` Christian Brauner
2020-03-08 21:38                                                 ` [PATCH v2 4/5] exec: Move exec_mmap right after de_thread in flush_old_exec Eric W. Biederman
2020-03-09 19:34                                                   ` Bernd Edlinger
2020-03-09 19:45                                                     ` Eric W. Biederman
2020-03-09 19:52                                                       ` Bernd Edlinger
2020-03-09 19:58                                                         ` Eric W. Biederman
2020-03-09 20:03                                                           ` Bernd Edlinger
2020-03-09 20:35                                                             ` Eric W. Biederman
2020-03-10 20:44                                                   ` Kees Cook
2020-03-10 21:20                                                     ` Eric W. Biederman
2020-03-10 20:47                                                   ` Kees Cook
2020-03-10 21:09                                                     ` Eric W. Biederman
2020-03-08 21:38                                                 ` [PATCH v2 5/5] exec: Add a exec_update_mutex to replace cred_guard_mutex Eric W. Biederman
2020-03-09 13:45                                                   ` Bernd Edlinger
2020-03-09 17:40                                                     ` Eric W. Biederman
2020-03-09 18:01                                                       ` Bernd Edlinger
2020-03-09 18:10                                                         ` Eric W. Biederman
2020-03-09 18:24                                                           ` Eric W. Biederman
2020-03-09 18:36                                                             ` Eric W. Biederman
2020-03-09 18:47                                                               ` Bernd Edlinger
2020-03-09 19:02                                                                 ` Eric W. Biederman
2020-03-09 19:24                                                                   ` Bernd Edlinger
2020-03-09 19:35                                                                     ` Eric W. Biederman
2020-03-09 19:39                                                                     ` Eric W. Biederman
2020-03-10 13:43                                                                       ` [PATCH 0/4] Use new infrastructure to fix deadlocks in execve Bernd Edlinger
2020-03-10 15:35                                                                         ` Eric W. Biederman
2020-03-10 17:44                                                                           ` [PATCH 0/4] Use new infrastructure in more simple cases Bernd Edlinger
2020-03-10 17:45                                                                           ` [PATCH 1/4] kernel/kcmp.c: Use new infrastructure to fix deadlocks in execve Bernd Edlinger
2020-03-10 19:01                                                                             ` Eric W. Biederman
2020-03-10 19:42                                                                               ` Bernd Edlinger
2020-03-10 17:45                                                                           ` [PATCH 2/4] proc: " Bernd Edlinger
2020-03-11 18:59                                                                             ` Kees Cook
2020-03-11 19:10                                                                             ` Kees Cook
2020-03-11 19:38                                                                               ` Bernd Edlinger
2020-03-10 17:45                                                                           ` [PATCH 3/4] proc: io_accounting: " Bernd Edlinger
2020-03-10 19:06                                                                             ` Eric W. Biederman
2020-03-10 20:19                                                                               ` Bernd Edlinger
2020-03-10 21:25                                                                                 ` Eric W. Biederman
2020-03-11 19:08                                                                             ` Kees Cook
2020-03-11 19:48                                                                               ` Bernd Edlinger
2020-03-11 19:48                                                                               ` Eric W. Biederman
2020-03-10 17:45                                                                           ` [PATCH 4/4] perf: " Bernd Edlinger
2020-03-10 13:43                                                                       ` [PATCH 1/4] exec: Fix a deadlock in ptrace Bernd Edlinger
2020-03-10 15:13                                                                         ` Eric W. Biederman
2020-03-10 15:17                                                                           ` Bernd Edlinger
2020-03-10 21:00                                                                         ` Kees Cook
2020-03-10 13:44                                                                       ` [PATCH 2/4] selftests/ptrace: add test cases for dead-locks Bernd Edlinger
2020-03-10 21:36                                                                         ` Kees Cook
2020-03-10 22:41                                                                         ` Dmitry V. Levin
2020-03-10 13:44                                                                       ` [PATCH 3/4] mm: docs: Fix a comment in process_vm_rw_core Bernd Edlinger
2020-03-11 18:53                                                                         ` Kees Cook
2020-03-10 13:44                                                                       ` [PATCH 4/4] kernel: doc: remove outdated comment cred.c Bernd Edlinger
2020-03-11 18:54                                                                         ` Kees Cook
2020-03-09 19:33                                                                   ` [PATCH v2 5/5] exec: Add a exec_update_mutex to replace cred_guard_mutex Dmitry V. Levin
2020-03-09 19:42                                                                     ` Eric W. Biederman
2020-03-10 20:55                                                                   ` Kees Cook
2020-03-10 21:02                                                                     ` Eric W. Biederman
2020-03-10 21:21                                                   ` Jann Horn
2020-03-10 21:30                                                     ` Eric W. Biederman
2020-03-10 23:21                                                       ` Jann Horn
2020-03-11  0:15                                                         ` Eric W. Biederman
2020-03-11  6:33                                                           ` Bernd Edlinger
2020-03-11 16:29                                                             ` Eric W. Biederman
2020-03-11 13:18                                                   ` Qian Cai
2020-03-12 10:27                                                   ` Kirill Tkhai
2020-03-12 12:24                                                     ` Eric W. Biederman
2020-03-12 13:45                                                       ` Kirill Tkhai
2020-03-12 14:38                                                         ` Eric W. Biederman
2020-03-12 15:23                                                           ` Kirill Tkhai
2020-03-13  1:05                                                           ` Bernd Edlinger
2020-03-13  9:13                                                             ` Kirill Tkhai
2020-03-14  9:11                                                               ` [PATCH v3 " Bernd Edlinger
2020-03-17  8:56                                                                 ` Kirill Tkhai
2020-03-17 21:53                                                                   ` Bernd Edlinger
2020-03-18 12:22                                                                     ` Kirill Tkhai
2020-03-18 20:06                                                                       ` Bernd Edlinger
2020-03-19  7:13                                                                         ` Kirill Tkhai
2020-03-19  7:19                                                                           ` Bernd Edlinger
2020-03-19  9:11                                                                           ` [PATCH v4 3/5] " Bernd Edlinger
2020-03-19  9:13                                                                             ` Bernd Edlinger
2020-03-19  9:19                                                                               ` Greg Kroah-Hartman
2020-03-19  9:20                                                                                 ` Bernd Edlinger
2020-03-21 22:53                                                                                 ` Bernd Edlinger
2020-03-14  9:12                                                               ` [PATCH 0/2] exec: Fix dead-lock in de_thread with ptrace_attach Bernd Edlinger
2020-03-14  9:12                                                               ` [PATCH 1/2] " Bernd Edlinger
2020-03-14  9:13                                                               ` [PATCH 2/2] doc: Update documentation of ->exec_*_mutex Bernd Edlinger
2020-03-14  9:57                                                               ` [PATCH v2 5/5] exec: Add a exec_update_mutex to replace cred_guard_mutex Bernd Edlinger
2020-03-14 10:02                                                                 ` Bernd Edlinger
2020-03-17  8:58                                                                   ` Kirill Tkhai
2020-03-09 13:58                                                 ` [PATCH 0/5] Infrastructure to allow fixing exec deadlocks Bernd Edlinger
2020-03-03 16:50                                 ` [PATCHv5] exec: Fix a deadlock in ptrace Christian Brauner
2020-03-02 12:28         ` [PATCHv2] " Oleg Nesterov
2020-03-02 15:56           ` Bernd Edlinger
2020-03-02  7:47       ` [PATCH] " Christian Brauner
2020-03-02  7:48         ` Christian Brauner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=AM6PR03MB5170D68B5010FCA627A603F8E4E60@AM6PR03MB5170.eurprd03.prod.outlook.com \
    --to=bernd.edlinger@hotmail.de \
    --cc=aarcange@redhat.com \
    --cc=adobriyan@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=anshuman.khandual@arm.com \
    --cc=avagin@gmail.com \
    --cc=bigeasy@linutronix.de \
    --cc=christian.brauner@ubuntu.com \
    --cc=christian@kellner.me \
    --cc=corbet@lwn.net \
    --cc=cyphar@cyphar.com \
    --cc=david@redhat.com \
    --cc=dhowells@redhat.com \
    --cc=duyuyang@gmail.com \
    --cc=ebiederm@xmission.com \
    --cc=frederic@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jamorris@linux.microsoft.com \
    --cc=jannh@google.com \
    --cc=jgg@ziepe.ca \
    --cc=keescook@chromium.org \
    --cc=ldv@altlinux.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mingo@kernel.org \
    --cc=oleg@redhat.com \
    --cc=peterz@infradead.org \
    --cc=shakeelb@google.com \
    --cc=tglx@linutronix.de \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).