• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- sanitizer_stoptheworld_linux.cc -----------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // See sanitizer_stoptheworld.h for details.
11 // This implementation was inspired by Markus Gutschke's linuxthreads.cc.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifdef __linux__
16 
17 #include "sanitizer_stoptheworld.h"
18 
19 #include <errno.h>
20 #include <sched.h> // for clone
21 #include <stddef.h>
22 #include <sys/prctl.h> // for PR_* definitions
23 #include <sys/ptrace.h> // for PTRACE_* definitions
24 #include <sys/types.h> // for pid_t
25 #include <sys/wait.h> // for signal-related stuff
26 
27 #include "sanitizer_common.h"
28 #include "sanitizer_libc.h"
29 #include "sanitizer_linux.h"
30 #include "sanitizer_mutex.h"
31 #include "sanitizer_placement_new.h"
32 
33 // This module works by spawning a Linux task which then attaches to every
34 // thread in the caller process with ptrace. This suspends the threads, and
35 // PTRACE_GETREGS can then be used to obtain their register state. The callback
36 // supplied to StopTheWorld() is run in the tracer task while the threads are
37 // suspended.
38 // The tracer task must be placed in a different thread group for ptrace to
39 // work, so it cannot be spawned as a pthread. Instead, we use the low-level
40 // clone() interface (we want to share the address space with the caller
41 // process, so we prefer clone() over fork()).
42 //
43 // We avoid the use of libc for two reasons:
44 // 1. calling a library function while threads are suspended could cause a
45 // deadlock, if one of the treads happens to be holding a libc lock;
46 // 2. it's generally not safe to call libc functions from the tracer task,
47 // because clone() does not set up a thread-local storage for it. Any
48 // thread-local variables used by libc will be shared between the tracer task
49 // and the thread which spawned it.
50 //
51 // We deal with this by replacing libc calls with calls to our own
52 // implementations defined in sanitizer_libc.h and sanitizer_linux.h. However,
53 // there are still some libc functions which are used here:
54 //
55 // * All of the system calls ultimately go through the libc syscall() function.
56 // We're operating under the assumption that syscall()'s implementation does
57 // not acquire any locks or use any thread-local data (except for the errno
58 // variable, which we handle separately).
59 //
60 // * We lack custom implementations of sigfillset() and sigaction(), so we use
61 // the libc versions instead. The same assumptions as above apply.
62 //
63 // * It is safe to call libc functions before the cloned thread is spawned or
64 // after it has exited. The following functions are used in this manner:
65 // sigdelset()
66 // sigprocmask()
67 // clone()
68 
69 COMPILER_CHECK(sizeof(SuspendedThreadID) == sizeof(pid_t));
70 
71 namespace __sanitizer {
72 // This class handles thread suspending/unsuspending in the tracer thread.
73 class ThreadSuspender {
74  public:
ThreadSuspender(pid_t pid)75   explicit ThreadSuspender(pid_t pid)
76     : pid_(pid) {
77       CHECK_GE(pid, 0);
78     }
79   bool SuspendAllThreads();
80   void ResumeAllThreads();
81   void KillAllThreads();
suspended_threads_list()82   SuspendedThreadsList &suspended_threads_list() {
83     return suspended_threads_list_;
84   }
85  private:
86   SuspendedThreadsList suspended_threads_list_;
87   pid_t pid_;
88   bool SuspendThread(SuspendedThreadID thread_id);
89 };
90 
SuspendThread(SuspendedThreadID thread_id)91 bool ThreadSuspender::SuspendThread(SuspendedThreadID thread_id) {
92   // Are we already attached to this thread?
93   // Currently this check takes linear time, however the number of threads is
94   // usually small.
95   if (suspended_threads_list_.Contains(thread_id))
96     return false;
97   if (internal_ptrace(PTRACE_ATTACH, thread_id, NULL, NULL) != 0) {
98     // Either the thread is dead, or something prevented us from attaching.
99     // Log this event and move on.
100     Report("Could not attach to thread %d (errno %d).\n", thread_id, errno);
101     return false;
102   } else {
103     if (SanitizerVerbosity > 0)
104       Report("Attached to thread %d.\n", thread_id);
105     // The thread is not guaranteed to stop before ptrace returns, so we must
106     // wait on it.
107     int waitpid_status;
108     HANDLE_EINTR(waitpid_status, internal_waitpid(thread_id, NULL, __WALL));
109     if (waitpid_status < 0) {
110       // Got a ECHILD error. I don't think this situation is possible, but it
111       // doesn't hurt to report it.
112       Report("Waiting on thread %d failed, detaching (errno %d).\n", thread_id,
113              errno);
114       internal_ptrace(PTRACE_DETACH, thread_id, NULL, NULL);
115       return false;
116     }
117     suspended_threads_list_.Append(thread_id);
118     return true;
119   }
120 }
121 
ResumeAllThreads()122 void ThreadSuspender::ResumeAllThreads() {
123   for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) {
124     pid_t tid = suspended_threads_list_.GetThreadID(i);
125     if (internal_ptrace(PTRACE_DETACH, tid, NULL, NULL) == 0) {
126       if (SanitizerVerbosity > 0)
127         Report("Detached from thread %d.\n", tid);
128     } else {
129       // Either the thread is dead, or we are already detached.
130       // The latter case is possible, for instance, if this function was called
131       // from a signal handler.
132       Report("Could not detach from thread %d (errno %d).\n", tid, errno);
133     }
134   }
135 }
136 
KillAllThreads()137 void ThreadSuspender::KillAllThreads() {
138   for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++)
139     internal_ptrace(PTRACE_KILL, suspended_threads_list_.GetThreadID(i),
140                     NULL, NULL);
141 }
142 
SuspendAllThreads()143 bool ThreadSuspender::SuspendAllThreads() {
144   void *mem = InternalAlloc(sizeof(ThreadLister));
145   ThreadLister *thread_lister = new(mem) ThreadLister(pid_);
146   bool added_threads;
147   do {
148     // Run through the directory entries once.
149     added_threads = false;
150     pid_t tid = thread_lister->GetNextTID();
151     while (tid >= 0) {
152       if (SuspendThread(tid))
153         added_threads = true;
154       tid = thread_lister->GetNextTID();
155     }
156     if (thread_lister->error()) {
157       // Detach threads and fail.
158       ResumeAllThreads();
159       InternalFree(mem);
160       return false;
161     }
162     thread_lister->Reset();
163   } while (added_threads);
164   InternalFree(mem);
165   return true;
166 }
167 
168 // Pointer to the ThreadSuspender instance for use in signal handler.
169 static ThreadSuspender *thread_suspender_instance = NULL;
170 
171 // Signals that should not be blocked (this is used in the parent thread as well
172 // as the tracer thread).
173 static const int kUnblockedSignals[] = { SIGABRT, SIGILL, SIGFPE, SIGSEGV,
174                                          SIGBUS, SIGXCPU, SIGXFSZ };
175 
176 // Structure for passing arguments into the tracer thread.
177 struct TracerThreadArgument {
178   StopTheWorldCallback callback;
179   void *callback_argument;
180   // The tracer thread waits on this mutex while the parent finished its
181   // preparations.
182   BlockingMutex mutex;
183 };
184 
185 // Signal handler to wake up suspended threads when the tracer thread dies.
TracerThreadSignalHandler(int signum,siginfo_t * siginfo,void *)186 void TracerThreadSignalHandler(int signum, siginfo_t *siginfo, void *) {
187   if (thread_suspender_instance != NULL) {
188     if (signum == SIGABRT)
189       thread_suspender_instance->KillAllThreads();
190     else
191       thread_suspender_instance->ResumeAllThreads();
192   }
193   internal__exit((signum == SIGABRT) ? 1 : 2);
194 }
195 
196 // Size of alternative stack for signal handlers in the tracer thread.
197 static const int kHandlerStackSize = 4096;
198 
199 // This function will be run as a cloned task.
TracerThread(void * argument)200 static int TracerThread(void* argument) {
201   TracerThreadArgument *tracer_thread_argument =
202       (TracerThreadArgument *)argument;
203 
204   // Wait for the parent thread to finish preparations.
205   tracer_thread_argument->mutex.Lock();
206   tracer_thread_argument->mutex.Unlock();
207 
208   ThreadSuspender thread_suspender(internal_getppid());
209   // Global pointer for the signal handler.
210   thread_suspender_instance = &thread_suspender;
211 
212   // Alternate stack for signal handling.
213   InternalScopedBuffer<char> handler_stack_memory(kHandlerStackSize);
214   struct sigaltstack handler_stack;
215   internal_memset(&handler_stack, 0, sizeof(handler_stack));
216   handler_stack.ss_sp = handler_stack_memory.data();
217   handler_stack.ss_size = kHandlerStackSize;
218   internal_sigaltstack(&handler_stack, NULL);
219 
220   // Install our handler for fatal signals. Other signals should be blocked by
221   // the mask we inherited from the caller thread.
222   for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals);
223        signal_index++) {
224     struct sigaction new_sigaction;
225     internal_memset(&new_sigaction, 0, sizeof(new_sigaction));
226     new_sigaction.sa_sigaction = TracerThreadSignalHandler;
227     new_sigaction.sa_flags = SA_ONSTACK | SA_SIGINFO;
228     sigfillset(&new_sigaction.sa_mask);
229     sigaction(kUnblockedSignals[signal_index], &new_sigaction, NULL);
230   }
231 
232   int exit_code = 0;
233   if (!thread_suspender.SuspendAllThreads()) {
234     Report("Failed suspending threads.\n");
235     exit_code = 3;
236   } else {
237     tracer_thread_argument->callback(thread_suspender.suspended_threads_list(),
238                                      tracer_thread_argument->callback_argument);
239     thread_suspender.ResumeAllThreads();
240     exit_code = 0;
241   }
242   thread_suspender_instance = NULL;
243   handler_stack.ss_flags = SS_DISABLE;
244   internal_sigaltstack(&handler_stack, NULL);
245   return exit_code;
246 }
247 
248 static sigset_t blocked_sigset;
249 static sigset_t old_sigset;
250 static struct sigaction old_sigactions[ARRAY_SIZE(kUnblockedSignals)];
251 
StopTheWorld(StopTheWorldCallback callback,void * argument)252 void StopTheWorld(StopTheWorldCallback callback, void *argument) {
253   // Block all signals that can be blocked safely, and install default handlers
254   // for the remaining signals.
255   // We cannot allow user-defined handlers to run while the ThreadSuspender
256   // thread is active, because they could conceivably call some libc functions
257   // which modify errno (which is shared between the two threads).
258   sigfillset(&blocked_sigset);
259   for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals);
260        signal_index++) {
261     // Remove the signal from the set of blocked signals.
262     sigdelset(&blocked_sigset, kUnblockedSignals[signal_index]);
263     // Install the default handler.
264     struct sigaction new_sigaction;
265     internal_memset(&new_sigaction, 0, sizeof(new_sigaction));
266     new_sigaction.sa_handler = SIG_DFL;
267     sigfillset(&new_sigaction.sa_mask);
268     sigaction(kUnblockedSignals[signal_index], &new_sigaction,
269                     &old_sigactions[signal_index]);
270   }
271   int sigprocmask_status = sigprocmask(SIG_BLOCK, &blocked_sigset, &old_sigset);
272   CHECK_EQ(sigprocmask_status, 0); // sigprocmask should never fail
273   // Make this process dumpable. Processes that are not dumpable cannot be
274   // attached to.
275   int process_was_dumpable = internal_prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
276   if (!process_was_dumpable)
277     internal_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
278   // Prepare the arguments for TracerThread.
279   struct TracerThreadArgument tracer_thread_argument;
280   tracer_thread_argument.callback = callback;
281   tracer_thread_argument.callback_argument = argument;
282   // Block the execution of TracerThread until after we have set ptrace
283   // permissions.
284   tracer_thread_argument.mutex.Lock();
285   // The tracer thread will run on the same stack, so we must reserve some
286   // stack space for the caller thread to run in as it waits on the tracer.
287   const uptr kReservedStackSize = 4096;
288   // Get a 16-byte aligned pointer for stack.
289   int a_local_variable __attribute__((__aligned__(16)));
290   pid_t tracer_pid = clone(TracerThread,
291                           (char *)&a_local_variable - kReservedStackSize,
292                           CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_UNTRACED,
293                           &tracer_thread_argument, 0, 0, 0);
294   if (tracer_pid < 0) {
295     Report("Failed spawning a tracer thread (errno %d).\n", errno);
296     tracer_thread_argument.mutex.Unlock();
297   } else {
298     // On some systems we have to explicitly declare that we want to be traced
299     // by the tracer thread.
300 #ifdef PR_SET_PTRACER
301     internal_prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);
302 #endif
303     // Allow the tracer thread to start.
304     tracer_thread_argument.mutex.Unlock();
305     // Since errno is shared between this thread and the tracer thread, we
306     // must avoid using errno while the tracer thread is running.
307     // At this point, any signal will either be blocked or kill us, so waitpid
308     // should never return (and set errno) while the tracer thread is alive.
309     int waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL);
310     if (waitpid_status < 0)
311       Report("Waiting on the tracer thread failed (errno %d).\n", errno);
312   }
313   // Restore the dumpable flag.
314   if (!process_was_dumpable)
315     internal_prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
316   // Restore the signal handlers.
317   for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals);
318        signal_index++) {
319     sigaction(kUnblockedSignals[signal_index],
320               &old_sigactions[signal_index], NULL);
321   }
322   sigprocmask(SIG_SETMASK, &old_sigset, &old_sigset);
323 }
324 
325 }  // namespace __sanitizer
326 
327 #endif  // __linux__
328