15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Copyright (c) 2005-2007, Google Inc. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * modification, are permitted provided that the following conditions are 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * met: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Redistributions in binary form must reproduce the above 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in the documentation and/or other materials provided with the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distribution. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * contributors may be used to endorse or promote products derived from 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this software without specific prior written permission. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * --- 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Author: Markus Gutschke 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/linuxthreads.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef THREADS 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __cplusplus 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sched.h> 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <signal.h> 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h> 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/wait.h> 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/linux_syscall_support.h" 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/thread_lister.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CLONE_UNTRACED 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CLONE_UNTRACED 0x00800000 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Synchronous signals that should not be blocked while in the lister thread. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int sync_signals[] = { SIGABRT, SIGILL, SIGFPE, SIGSEGV, SIGBUS, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SIGXCPU, SIGXFSZ }; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* itoa() is not a standard function, and we cannot safely call printf() 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * after suspending threads. So, we just implement our own copy. A 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * recursive approach is the easiest here. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char *local_itoa(char *buf, int i) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i < 0) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buf++ = '-'; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return local_itoa(buf, -i); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i >= 10) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf = local_itoa(buf, i/10); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buf++ = (i%10) + '0'; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *buf = '\000'; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buf; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Wrapper around clone() that runs "fn" on the same stack as the 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * caller! Unlike fork(), the cloned thread shares the same address space. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The caller must be careful to use only minimal amounts of stack until 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the cloned thread has returned. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * There is a good chance that the cloned thread and the caller will share 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the same copy of errno! 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__ 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if __GNUC__ == 3 && __GNUC_MINOR__ >= 1 || __GNUC__ > 3 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Try to force this function into a separate stack frame, and make sure 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that arguments are passed on the stack. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int local_clone (int (*fn)(void *), void *arg, ...) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __attribute__ ((noinline)); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int local_clone (int (*fn)(void *), void *arg, ...) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Leave 4kB of gap between the callers stack and the new clone. This 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * should be more than sufficient for the caller to call waitpid() until 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the cloned thread terminates. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * It is important that we set the CLONE_UNTRACED flag, because newer 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * versions of "gdb" otherwise attempt to attach to our thread, and will 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * attempt to reap its status codes. This subsequently results in the 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * caller hanging indefinitely in waitpid(), waiting for a change in 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * status that will never happen. By setting the CLONE_UNTRACED flag, we 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * prevent "gdb" from stealing events, but we still expect the thread 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * lister to fail, because it cannot PTRACE_ATTACH to the process that 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is being debugged. This is OK and the error code will be reported 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * correctly. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sys_clone(fn, (char *)&arg - 4096, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_UNTRACED, arg, 0, 0, 0); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Local substitute for the atoi() function, which is not necessarily safe 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to call once threads are suspended (depending on whether libc looks up 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * locale information, when executing atoi()). 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int local_atoi(const char *s) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int n = 0; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int neg = *s == '-'; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (neg) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s++; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (*s >= '0' && *s <= '9') 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n = 10*n + (*s++ - '0'); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return neg ? -n : n; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Re-runs fn until it doesn't cause EINTR 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Wrap a class around system calls, in order to give us access to 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a private copy of errno. This only works in C++, but it has the 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * advantage of not needing nested functions, which are a non-standard 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * language extension. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __cplusplus 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class SysCalls { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SYS_CPLUSPLUS 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SYS_ERRNO my_errno 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SYS_INLINE inline 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SYS_PREFIX -1 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #undef SYS_LINUX_SYSCALL_SUPPORT_H 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #include "linux_syscall_support.h" 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SysCalls() : my_errno(0) { } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int my_errno; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ERRNO sys.my_errno 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ERRNO my_errno 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Wrapper for open() which is guaranteed to never return EINTR. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int c_open(const char *fname, int flags, int mode) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssize_t rc; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NO_INTR(rc = sys_open(fname, flags, mode)); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* abort() is not safely reentrant, and changes it's behavior each time 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * it is called. This means, if the main application ever called abort() 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * we cannot safely call it again. This would happen if we were called 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * from a SIGABRT signal handler in the main application. So, document 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that calling SIGABRT from the thread lister makes it not signal safe 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (and vice-versa). 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Also, since we share address space with the main application, we 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * cannot call abort() from the callback and expect the main application 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to behave correctly afterwards. In fact, the only thing we can do, is 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to terminate the main application with extreme prejudice (aka 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PTRACE_KILL). 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We set up our own SIGABRT handler to do this. 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In order to find the main application from the signal handler, we 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * need to store information about it in global variables. This is 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * safe, because the main application should be suspended at this 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * time. If the callback ever called ResumeAllProcessThreads(), then 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * we are running a higher risk, though. So, try to avoid calling 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * abort() after calling ResumeAllProcessThreads. 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static volatile int *sig_pids, sig_num_threads, sig_proc, sig_marker; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Signal handler to help us recover from dying while we are attached to 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * other threads. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void SignalHandler(int signum, siginfo_t *si, void *data) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sig_pids != NULL) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (signum == SIGABRT) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (sig_num_threads-- > 0) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Not sure if sched_yield is really necessary here, but it does not */ 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* hurt, and it might be necessary for the same reasons that we have */ 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* to do so in sys_ptrace_detach(). */ 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_sched_yield(); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_ptrace(PTRACE_KILL, sig_pids[sig_num_threads], 0, 0); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (sig_num_threads > 0) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResumeAllProcessThreads(sig_num_threads, (int *)sig_pids); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_pids = NULL; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sig_marker >= 0) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NO_INTR(sys_close(sig_marker)); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_marker = -1; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sig_proc >= 0) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NO_INTR(sys_close(sig_proc)); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_proc = -1; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys__exit(signum == SIGABRT ? 1 : 2); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Try to dirty the stack, and hope that the compiler is not smart enough 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to optimize this function away. Or worse, the compiler could inline the 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * function and permanently allocate the data on the stack. 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DirtyStack(size_t amount) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[amount]; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(buf, 0, amount); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_read(-1, buf, amount); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Data structure for passing arguments to the lister thread. 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ALT_STACKSIZE (MINSIGSTKSZ + 4096) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ListerParams { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result, err; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *altstack_mem; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListAllProcessThreadsCallBack callback; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *parameter; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_list ap; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ListerThread(struct ListerParams *args) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int found_parent = 0; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid_t clone_pid = sys_gettid(), ppid = sys_getppid(); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char proc_self_task[80], marker_name[48], *marker_path; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *proc_paths[3]; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *const *proc_path = proc_paths; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int proc = -1, marker = -1, num_threads = 0; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_threads = 0, sig; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct kernel_stat marker_sb, proc_sb; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_t altstack; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Create "marker" that we can use to detect threads sharing the same 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * address space and the same file handles. By setting the FD_CLOEXEC flag 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * we minimize the risk of misidentifying child processes as threads; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and since there is still a race condition, we will filter those out 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * later, anyway. 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((marker = sys_socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0 || 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_fcntl(marker, F_SETFD, FD_CLOEXEC) < 0) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) failure: 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->result = -1; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->err = errno; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (marker >= 0) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NO_INTR(sys_close(marker)); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_marker = marker = -1; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (proc >= 0) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NO_INTR(sys_close(proc)); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_proc = proc = -1; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys__exit(1); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Compute search paths for finding thread directories in /proc */ 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_itoa(strrchr(strcpy(proc_self_task, "/proc/"), '\000'), ppid); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcpy(marker_name, proc_self_task); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) marker_path = marker_name + strlen(marker_name); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcat(proc_self_task, "/task/"); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc_paths[0] = proc_self_task; /* /proc/$$/task/ */ 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc_paths[1] = "/proc/"; /* /proc/ */ 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) proc_paths[2] = NULL; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Compute path for marker socket in /proc */ 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local_itoa(strcpy(marker_path, "/fd/") + 4, marker); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sys_stat(marker_name, &marker_sb) < 0) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto failure; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Catch signals on an alternate pre-allocated stack. This way, we can 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * safely execute the signal handler even if we ran out of memory. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&altstack, 0, sizeof(altstack)); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) altstack.ss_sp = args->altstack_mem; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) altstack.ss_flags = 0; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) altstack.ss_size = ALT_STACKSIZE; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_sigaltstack(&altstack, (const stack_t *)NULL); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Some kernels forget to wake up traced processes, when the 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * tracer dies. So, intercept synchronous signals and make sure 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that we wake up our tracees before dying. It is the caller's 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * responsibility to ensure that asynchronous signals do not 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * interfere with this function. 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_marker = marker; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_proc = -1; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (sig = 0; sig < sizeof(sync_signals)/sizeof(*sync_signals); sig++) { 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct kernel_sigaction sa; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&sa, 0, sizeof(sa)); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sa.sa_sigaction_ = SignalHandler; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_sigfillset(&sa.sa_mask); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sa.sa_flags = SA_ONSTACK|SA_SIGINFO|SA_RESETHAND; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_sigaction(sync_signals[sig], &sa, (struct kernel_sigaction *)NULL); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Read process directories in /proc/... */ 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Some kernels know about threads, and hide them in "/proc" 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (although they are still there, if you know the process 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * id). Threads are moved into a separate "task" directory. We 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * check there first, and then fall back on the older naming 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * convention if necessary. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((sig_proc = proc = c_open(*proc_path, O_RDONLY|O_DIRECTORY, 0)) < 0) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*++proc_path != NULL) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto failure; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sys_fstat(proc, &proc_sb) < 0) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto failure; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Since we are suspending threads, we cannot call any libc 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * functions that might acquire locks. Most notably, we cannot 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * call malloc(). So, we have to allocate memory on the stack, 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * instead. Since we do not know how much memory we need, we 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * make a best guess. And if we guessed incorrectly we retry on 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a second iteration (by jumping to "detach_threads"). 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Unless the number of threads is increasing very rapidly, we 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * should never need to do so, though, as our guestimate is very 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * conservative. 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (max_threads < proc_sb.st_nlink + 100) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_threads = proc_sb.st_nlink + 100; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* scope */ { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid_t pids[max_threads]; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int added_entries = 0; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_num_threads = num_threads; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_pids = pids; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct kernel_dirent *entry; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[4096]; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssize_t nbytes = sys_getdents(proc, (struct kernel_dirent *)buf, 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(buf)); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nbytes < 0) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto failure; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (nbytes == 0) { 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (added_entries) { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Need to keep iterating over "/proc" in multiple 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * passes until we no longer find any more threads. This 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * algorithm eventually completes, when all threads have 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * been suspended. 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) added_entries = 0; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_lseek(proc, 0, SEEK_SET); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (entry = (struct kernel_dirent *)buf; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry < (struct kernel_dirent *)&buf[nbytes]; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry = (struct kernel_dirent *)((char *)entry+entry->d_reclen)) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (entry->d_ino != 0) { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *ptr = entry->d_name; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid_t pid; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Some kernels hide threads by preceding the pid with a '.' */ 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*ptr == '.') 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr++; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If the directory is not numeric, it cannot be a 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * process/thread 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*ptr < '0' || *ptr > '9') 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid = local_atoi(ptr); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Attach (and suspend) all threads */ 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pid && pid != clone_pid) { 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct kernel_stat tmp_sb; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char fname[entry->d_reclen + 48]; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcat(strcat(strcpy(fname, "/proc/"), 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entry->d_name), marker_path); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check if the marker is identical to the one we created */ 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sys_stat(fname, &tmp_sb) >= 0 && 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) marker_sb.st_ino == tmp_sb.st_ino) { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long i, j; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Found one of our threads, make sure it is no duplicate */ 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < num_threads; i++) { 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Linear search is slow, but should not matter much for 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the typically small number of threads. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pids[i] == pid) { 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Found a duplicate; most likely on second pass */ 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto next_entry; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check whether data structure needs growing */ 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (num_threads >= max_threads) { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Back to square one, this time with more memory */ 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NO_INTR(sys_close(proc)); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto detach_threads; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Attaching to thread suspends it */ 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pids[num_threads++] = pid; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_num_threads = num_threads; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sys_ptrace(PTRACE_ATTACH, pid, (void *)0, 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void *)0) < 0) { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If operation failed, ignore thread. Maybe it 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * just died? There might also be a race 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * condition with a concurrent core dumper or 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * with a debugger. In that case, we will just 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * make a best effort, rather than failing 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * entirely. 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_threads--; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_num_threads = num_threads; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto next_entry; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (sys_waitpid(pid, (int *)0, __WALL) < 0) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (errno != EINTR) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_ptrace_detach(pid); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_threads--; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_num_threads = num_threads; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto next_entry; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i++ != j || 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i != j) { 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Address spaces are distinct, even though both 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * processes show the "marker". This is probably 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a forked child process rather than a thread. 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_ptrace_detach(pid); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_threads--; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_num_threads = num_threads; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_parent |= pid == ppid; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) added_entries++; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_entry:; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NO_INTR(sys_close(proc)); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_proc = proc = -1; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If we failed to find any threads, try looking somewhere else in 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * /proc. Maybe, threads are reported differently on this system. 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (num_threads > 1 || !*++proc_path) { 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NO_INTR(sys_close(marker)); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_marker = marker = -1; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If we never found the parent process, something is very wrong. 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Most likely, we are running in debugger. Any attempt to operate 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * on the threads would be very incomplete. Let's just report an 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * error to the caller. 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!found_parent) { 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResumeAllProcessThreads(num_threads, pids); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys__exit(3); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Now we are ready to call the callback, 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * which takes care of resuming the threads for us. 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->result = args->callback(args->parameter, num_threads, 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pids, args->ap); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->err = errno; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Callback should have resumed threads, but better safe than sorry */ 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ResumeAllProcessThreads(num_threads, pids)) { 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Callback forgot to resume at least one thread, report error */ 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->err = EINVAL; 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->result = -1; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys__exit(0); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detach_threads: 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Resume all threads prior to retrying the operation */ 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResumeAllProcessThreads(num_threads, pids); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_pids = NULL; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_threads = 0; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sig_num_threads = num_threads; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_threads += 100; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* This function gets the list of all linux threads of the current process 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * passes them to the 'callback' along with the 'parameter' pointer; at the 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * call back call time all the threads are paused via 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PTRACE_ATTACH. 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The callback is executed from a separate thread which shares only the 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * address space, the filesystem, and the filehandles with the caller. Most 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notably, it does not share the same pid and ppid; and if it terminates, 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the rest of the application is still there. 'callback' is supposed to do 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * or arrange for ResumeAllProcessThreads. This happens automatically, if 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the thread raises a synchronous signal (e.g. SIGSEGV); asynchronous 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * signals are blocked. If the 'callback' decides to unblock them, it must 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ensure that they cannot terminate the application, or that 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ResumeAllProcessThreads will get called. 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * It is an error for the 'callback' to make any library calls that could 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * acquire locks. Most notably, this means that most system calls have to 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * avoid going through libc. Also, this means that it is not legal to call 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * exit() or abort(). 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We return -1 on error and the return value of 'callback' on success. 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ListAllProcessThreads(void *parameter, 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListAllProcessThreadsCallBack callback, ...) { 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char altstack_mem[ALT_STACKSIZE]; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct ListerParams args; 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid_t clone_pid; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int dumpable = 1, sig; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct kernel_sigset_t sig_blocked, sig_old; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_start(args.ap, callback); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If we are short on virtual memory, initializing the alternate stack 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * might trigger a SIGSEGV. Let's do this early, before it could get us 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * into more trouble (i.e. before signal handlers try to use the alternate 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * stack, and before we attach to other threads). 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(altstack_mem, 0, sizeof(altstack_mem)); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Some of our cleanup functions could conceivable use more stack space. 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Try to touch the stack right now. This could be defeated by the compiler 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * being too smart for it's own good, so try really hard. 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DirtyStack(32768); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Make this process "dumpable". This is necessary in order to ptrace() 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * after having called setuid(). 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dumpable = sys_prctl(PR_GET_DUMPABLE, 0); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dumpable) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_prctl(PR_SET_DUMPABLE, 1); 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Fill in argument block for dumper thread */ 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.result = -1; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.err = 0; 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.altstack_mem = altstack_mem; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.parameter = parameter; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.callback = callback; 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Before cloning the thread lister, block all asynchronous signals, as we */ 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* are not prepared to handle them. */ 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_sigfillset(&sig_blocked); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (sig = 0; sig < sizeof(sync_signals)/sizeof(*sync_signals); sig++) { 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_sigdelset(&sig_blocked, sync_signals[sig]); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sys_sigprocmask(SIG_BLOCK, &sig_blocked, &sig_old)) { 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.err = errno; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.result = -1; 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto failed; 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* scope */ { 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* After cloning, both the parent and the child share the same instance 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of errno. We must make sure that at least one of these processes 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (in our case, the parent) uses modified syscall macros that update 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * a local copy of errno, instead. 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #ifdef __cplusplus 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define sys0_sigprocmask sys.sigprocmask 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define sys0_waitpid sys.waitpid 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SysCalls sys; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #else 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int my_errno; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SYS_ERRNO my_errno 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SYS_INLINE inline 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define SYS_PREFIX 0 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #undef SYS_LINUX_SYSCALL_SUPPORT_H 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #include "linux_syscall_support.h" 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #endif 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int clone_errno; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clone_pid = local_clone((int (*)(void *))ListerThread, &args); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clone_errno = errno; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_sigprocmask(SIG_SETMASK, &sig_old, &sig_old); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (clone_pid >= 0) { 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int status, rc; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((rc = sys0_waitpid(clone_pid, &status, __WALL)) < 0 && 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ERRNO == EINTR) { 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Keep waiting */ 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rc < 0) { 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.err = ERRNO; 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.result = -1; 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (WIFEXITED(status)) { 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (WEXITSTATUS(status)) { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 0: break; /* Normal process termination */ 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 2: args.err = EFAULT; /* Some fault (e.g. SIGSEGV) detected */ 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.result = -1; 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 3: args.err = EPERM; /* Process is already being traced */ 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.result = -1; 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default:args.err = ECHILD; /* Child died unexpectedly */ 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.result = -1; 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!WIFEXITED(status)) { 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.err = EFAULT; /* Terminated due to an unhandled signal*/ 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.result = -1; 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.result = -1; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.err = clone_errno; 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Restore the "dumpable" state of the process */ 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)failed: 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dumpable) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys_prctl(PR_SET_DUMPABLE, dumpable); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_end(args.ap); 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = args.err; 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return args.result; 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* This function resumes the list of all linux threads that 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ListAllProcessThreads pauses before giving to its callback. 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The function returns non-zero if at least one thread was 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * suspended and has now been resumed. 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ResumeAllProcessThreads(int num_threads, pid_t *thread_pids) { 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int detached_at_least_one = 0; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (num_threads-- > 0) { 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) detached_at_least_one |= sys_ptrace_detach(thread_pids[num_threads]) >= 0; 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return detached_at_least_one; 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __cplusplus 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 666