diff options
author | Andreas Schwab <schwab@suse.de> | 2013-07-30 11:58:45 +0200 |
---|---|---|
committer | Andreas Schwab <schwab@suse.de> | 2014-02-25 09:29:34 +0100 |
commit | b04acb2651e0aaf615de50e9138cddfd5c24021f (patch) | |
tree | 4908e5a456a4316f468ac3bc8cce6437eb874250 | |
parent | d4ec6ae19e3290abbb3cfff70a8dd6018ecb6e2e (diff) | |
download | glibc-b04acb2651e0aaf615de50e9138cddfd5c24021f.tar.gz glibc-b04acb2651e0aaf615de50e9138cddfd5c24021f.tar.xz glibc-b04acb2651e0aaf615de50e9138cddfd5c24021f.zip |
Fix race conditions in pldd that may leave the process stopped after detaching
Fixes bug 15804
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | elf/pldd.c | 25 |
3 files changed, 32 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog index a9fe7a5cbc..9f28d70e19 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2014-02-24 Andreas Schwab <schwab@suse.de> + + [BZ #15804] + * elf/pldd.c (wait_for_ptrace_stop): New function. + (main): Call it after attaching. + 2014-02-22 Roland McGrath <roland@hack.frob.com> * Makerules ($(common-objpfx)Versions.v.i): No longer depend diff --git a/NEWS b/NEWS index dc5f380a1d..3698c404f0 100644 --- a/NEWS +++ b/NEWS @@ -9,7 +9,7 @@ Version 2.20 * The following bugs are resolved with this release: - 15894, 16447, 16545, 16574, 16600, 16609, 16610, 16611. + 15804, 15894, 16447, 16545, 16574, 16600, 16609, 16610, 16611. * The am33 port, which had not worked for several years, has been removed from ports. diff --git a/elf/pldd.c b/elf/pldd.c index 684aff4dba..75f78120df 100644 --- a/elf/pldd.c +++ b/elf/pldd.c @@ -34,6 +34,7 @@ #include <unistd.h> #include <sys/ptrace.h> #include <sys/stat.h> +#include <sys/wait.h> #include <ldsodefs.h> #include <version.h> @@ -82,6 +83,7 @@ static char *exe; /* Local functions. */ static int get_process_info (int dfd, long int pid); +static void wait_for_ptrace_stop (long int pid); int @@ -170,6 +172,8 @@ main (int argc, char *argv[]) tid); } + wait_for_ptrace_stop (tid); + struct thread_list *newp = alloca (sizeof (*newp)); newp->tid = tid; newp->next = thread_list; @@ -194,6 +198,27 @@ main (int argc, char *argv[]) } +/* Wait for PID to enter ptrace-stop state after being attached. */ +static void +wait_for_ptrace_stop (long int pid) +{ + int status; + + /* While waiting for SIGSTOP being delivered to the tracee we have to + reinject any other pending signal. Ignore all other errors. */ + while (waitpid (pid, &status, __WALL) == pid && WIFSTOPPED (status)) + { + /* The STOP signal should not be delivered to the tracee. */ + if (WSTOPSIG (status) == SIGSTOP) + return; + if (ptrace (PTRACE_CONT, pid, NULL, + (void *) (uintptr_t) WSTOPSIG (status))) + /* The only possible error is that the process died. */ + return; + } +} + + /* Handle program arguments. */ static error_t parse_opt (int key, char *arg, struct argp_state *state) |