sanitizer_stoptheworld_linux_libcdep.cc revision c154820b43052cfc54ee20752a3232aa8e6c7843
1//===-- sanitizer_stoptheworld_linux_libcdep.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 16#include "sanitizer_platform.h" 17#if SANITIZER_LINUX 18 19#include "sanitizer_stoptheworld.h" 20 21#include <errno.h> 22#include <sched.h> // for clone 23#include <stddef.h> 24#include <sys/prctl.h> // for PR_* definitions 25#include <sys/ptrace.h> // for PTRACE_* definitions 26#include <sys/types.h> // for pid_t 27#if SANITIZER_ANDROID && defined(__arm__) 28# include <linux/user.h> // for pt_regs 29#else 30# include <sys/user.h> // for user_regs_struct 31#endif 32#include <sys/wait.h> // for signal-related stuff 33 34#include "sanitizer_common.h" 35#include "sanitizer_libc.h" 36#include "sanitizer_linux.h" 37#include "sanitizer_mutex.h" 38#include "sanitizer_placement_new.h" 39 40// This module works by spawning a Linux task which then attaches to every 41// thread in the caller process with ptrace. This suspends the threads, and 42// PTRACE_GETREGS can then be used to obtain their register state. The callback 43// supplied to StopTheWorld() is run in the tracer task while the threads are 44// suspended. 45// The tracer task must be placed in a different thread group for ptrace to 46// work, so it cannot be spawned as a pthread. Instead, we use the low-level 47// clone() interface (we want to share the address space with the caller 48// process, so we prefer clone() over fork()). 49// 50// We avoid the use of libc for two reasons: 51// 1. calling a library function while threads are suspended could cause a 52// deadlock, if one of the treads happens to be holding a libc lock; 53// 2. it's generally not safe to call libc functions from the tracer task, 54// because clone() does not set up a thread-local storage for it. Any 55// thread-local variables used by libc will be shared between the tracer task 56// and the thread which spawned it. 57// 58// We deal with this by replacing libc calls with calls to our own 59// implementations defined in sanitizer_libc.h and sanitizer_linux.h. However, 60// there are still some libc functions which are used here: 61// 62// * All of the system calls ultimately go through the libc syscall() function. 63// We're operating under the assumption that syscall()'s implementation does 64// not acquire any locks or use any thread-local data (except for the errno 65// variable, which we handle separately). 66// 67// * We lack custom implementations of sigfillset() and sigaction(), so we use 68// the libc versions instead. The same assumptions as above apply. 69// 70// * It is safe to call libc functions before the cloned thread is spawned or 71// after it has exited. The following functions are used in this manner: 72// sigdelset() 73// sigprocmask() 74// clone() 75 76COMPILER_CHECK(sizeof(SuspendedThreadID) == sizeof(pid_t)); 77 78namespace __sanitizer { 79// This class handles thread suspending/unsuspending in the tracer thread. 80class ThreadSuspender { 81 public: 82 explicit ThreadSuspender(pid_t pid) 83 : pid_(pid) { 84 CHECK_GE(pid, 0); 85 } 86 bool SuspendAllThreads(); 87 void ResumeAllThreads(); 88 void KillAllThreads(); 89 SuspendedThreadsList &suspended_threads_list() { 90 return suspended_threads_list_; 91 } 92 private: 93 SuspendedThreadsList suspended_threads_list_; 94 pid_t pid_; 95 bool SuspendThread(SuspendedThreadID thread_id); 96}; 97 98bool ThreadSuspender::SuspendThread(SuspendedThreadID thread_id) { 99 // Are we already attached to this thread? 100 // Currently this check takes linear time, however the number of threads is 101 // usually small. 102 if (suspended_threads_list_.Contains(thread_id)) 103 return false; 104 int pterrno; 105 if (internal_iserror(internal_ptrace(PTRACE_ATTACH, thread_id, NULL, NULL), 106 &pterrno)) { 107 // Either the thread is dead, or something prevented us from attaching. 108 // Log this event and move on. 109 Report("Could not attach to thread %d (errno %d).\n", thread_id, pterrno); 110 return false; 111 } else { 112 if (SanitizerVerbosity > 0) 113 Report("Attached to thread %d.\n", thread_id); 114 // The thread is not guaranteed to stop before ptrace returns, so we must 115 // wait on it. 116 uptr waitpid_status; 117 HANDLE_EINTR(waitpid_status, internal_waitpid(thread_id, NULL, __WALL)); 118 int wperrno; 119 if (internal_iserror(waitpid_status, &wperrno)) { 120 // Got a ECHILD error. I don't think this situation is possible, but it 121 // doesn't hurt to report it. 122 Report("Waiting on thread %d failed, detaching (errno %d).\n", thread_id, 123 wperrno); 124 internal_ptrace(PTRACE_DETACH, thread_id, NULL, NULL); 125 return false; 126 } 127 suspended_threads_list_.Append(thread_id); 128 return true; 129 } 130} 131 132void ThreadSuspender::ResumeAllThreads() { 133 for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) { 134 pid_t tid = suspended_threads_list_.GetThreadID(i); 135 int pterrno; 136 if (!internal_iserror(internal_ptrace(PTRACE_DETACH, tid, NULL, NULL), 137 &pterrno)) { 138 if (SanitizerVerbosity > 0) 139 Report("Detached from thread %d.\n", tid); 140 } else { 141 // Either the thread is dead, or we are already detached. 142 // The latter case is possible, for instance, if this function was called 143 // from a signal handler. 144 Report("Could not detach from thread %d (errno %d).\n", tid, pterrno); 145 } 146 } 147} 148 149void ThreadSuspender::KillAllThreads() { 150 for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) 151 internal_ptrace(PTRACE_KILL, suspended_threads_list_.GetThreadID(i), 152 NULL, NULL); 153} 154 155bool ThreadSuspender::SuspendAllThreads() { 156 ThreadLister thread_lister(pid_); 157 bool added_threads; 158 do { 159 // Run through the directory entries once. 160 added_threads = false; 161 pid_t tid = thread_lister.GetNextTID(); 162 while (tid >= 0) { 163 if (SuspendThread(tid)) 164 added_threads = true; 165 tid = thread_lister.GetNextTID(); 166 } 167 if (thread_lister.error()) { 168 // Detach threads and fail. 169 ResumeAllThreads(); 170 return false; 171 } 172 thread_lister.Reset(); 173 } while (added_threads); 174 return true; 175} 176 177// Pointer to the ThreadSuspender instance for use in signal handler. 178static ThreadSuspender *thread_suspender_instance = NULL; 179 180// Signals that should not be blocked (this is used in the parent thread as well 181// as the tracer thread). 182static const int kUnblockedSignals[] = { SIGABRT, SIGILL, SIGFPE, SIGSEGV, 183 SIGBUS, SIGXCPU, SIGXFSZ }; 184 185// Structure for passing arguments into the tracer thread. 186struct TracerThreadArgument { 187 StopTheWorldCallback callback; 188 void *callback_argument; 189 // The tracer thread waits on this mutex while the parent finished its 190 // preparations. 191 BlockingMutex mutex; 192}; 193 194static DieCallbackType old_die_callback; 195 196// Signal handler to wake up suspended threads when the tracer thread dies. 197void TracerThreadSignalHandler(int signum, siginfo_t *siginfo, void *) { 198 if (thread_suspender_instance != NULL) { 199 if (signum == SIGABRT) 200 thread_suspender_instance->KillAllThreads(); 201 else 202 thread_suspender_instance->ResumeAllThreads(); 203 } 204 internal__exit((signum == SIGABRT) ? 1 : 2); 205} 206 207static void TracerThreadDieCallback() { 208 // Generally a call to Die() in the tracer thread should be fatal to the 209 // parent process as well, because they share the address space. 210 // This really only works correctly if all the threads are suspended at this 211 // point. So we correctly handle calls to Die() from within the callback, but 212 // not those that happen before or after the callback. Hopefully there aren't 213 // a lot of opportunities for that to happen... 214 if (thread_suspender_instance) 215 thread_suspender_instance->KillAllThreads(); 216 if (old_die_callback) 217 old_die_callback(); 218} 219 220// Size of alternative stack for signal handlers in the tracer thread. 221static const int kHandlerStackSize = 4096; 222 223// This function will be run as a cloned task. 224static int TracerThread(void* argument) { 225 TracerThreadArgument *tracer_thread_argument = 226 (TracerThreadArgument *)argument; 227 228 // Wait for the parent thread to finish preparations. 229 tracer_thread_argument->mutex.Lock(); 230 tracer_thread_argument->mutex.Unlock(); 231 232 SetDieCallback(TracerThreadDieCallback); 233 234 ThreadSuspender thread_suspender(internal_getppid()); 235 // Global pointer for the signal handler. 236 thread_suspender_instance = &thread_suspender; 237 238 // Alternate stack for signal handling. 239 InternalScopedBuffer<char> handler_stack_memory(kHandlerStackSize); 240 struct sigaltstack handler_stack; 241 internal_memset(&handler_stack, 0, sizeof(handler_stack)); 242 handler_stack.ss_sp = handler_stack_memory.data(); 243 handler_stack.ss_size = kHandlerStackSize; 244 internal_sigaltstack(&handler_stack, NULL); 245 246 // Install our handler for fatal signals. Other signals should be blocked by 247 // the mask we inherited from the caller thread. 248 for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals); 249 signal_index++) { 250 struct sigaction new_sigaction; 251 internal_memset(&new_sigaction, 0, sizeof(new_sigaction)); 252 new_sigaction.sa_sigaction = TracerThreadSignalHandler; 253 new_sigaction.sa_flags = SA_ONSTACK | SA_SIGINFO; 254 sigfillset(&new_sigaction.sa_mask); 255 sigaction(kUnblockedSignals[signal_index], &new_sigaction, NULL); 256 } 257 258 int exit_code = 0; 259 if (!thread_suspender.SuspendAllThreads()) { 260 Report("Failed suspending threads.\n"); 261 exit_code = 3; 262 } else { 263 tracer_thread_argument->callback(thread_suspender.suspended_threads_list(), 264 tracer_thread_argument->callback_argument); 265 thread_suspender.ResumeAllThreads(); 266 exit_code = 0; 267 } 268 thread_suspender_instance = NULL; 269 handler_stack.ss_flags = SS_DISABLE; 270 internal_sigaltstack(&handler_stack, NULL); 271 return exit_code; 272} 273 274class ScopedStackSpaceWithGuard { 275 public: 276 explicit ScopedStackSpaceWithGuard(uptr stack_size) { 277 stack_size_ = stack_size; 278 guard_size_ = GetPageSizeCached(); 279 // FIXME: Omitting MAP_STACK here works in current kernels but might break 280 // in the future. 281 guard_start_ = (uptr)MmapOrDie(stack_size_ + guard_size_, 282 "ScopedStackWithGuard"); 283 CHECK_EQ(guard_start_, (uptr)Mprotect((uptr)guard_start_, guard_size_)); 284 } 285 ~ScopedStackSpaceWithGuard() { 286 UnmapOrDie((void *)guard_start_, stack_size_ + guard_size_); 287 } 288 void *Bottom() const { 289 return (void *)(guard_start_ + stack_size_ + guard_size_); 290 } 291 292 private: 293 uptr stack_size_; 294 uptr guard_size_; 295 uptr guard_start_; 296}; 297 298NOINLINE static void WipeStack() { 299 char arr[256]; 300 internal_memset(arr, 0, sizeof(arr)); 301} 302 303// We have a limitation on the stack frame size, so some stuff had to be moved 304// into globals. 305static sigset_t blocked_sigset; 306static sigset_t old_sigset; 307static struct sigaction old_sigactions[ARRAY_SIZE(kUnblockedSignals)]; 308 309class StopTheWorldScope { 310 public: 311 StopTheWorldScope() { 312 // Glibc's sigaction() has a side-effect where it copies garbage stack 313 // values into oldact, which can cause false negatives in LSan. As a quick 314 // workaround we zero some stack space here. 315 WipeStack(); 316 // Block all signals that can be blocked safely, and install 317 // default handlers for the remaining signals. 318 // We cannot allow user-defined handlers to run while the ThreadSuspender 319 // thread is active, because they could conceivably call some libc functions 320 // which modify errno (which is shared between the two threads). 321 sigfillset(&blocked_sigset); 322 for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals); 323 signal_index++) { 324 // Remove the signal from the set of blocked signals. 325 sigdelset(&blocked_sigset, kUnblockedSignals[signal_index]); 326 // Install the default handler. 327 struct sigaction new_sigaction; 328 internal_memset(&new_sigaction, 0, sizeof(new_sigaction)); 329 new_sigaction.sa_handler = SIG_DFL; 330 sigfillset(&new_sigaction.sa_mask); 331 sigaction(kUnblockedSignals[signal_index], &new_sigaction, 332 &old_sigactions[signal_index]); 333 } 334 int sigprocmask_status = 335 sigprocmask(SIG_BLOCK, &blocked_sigset, &old_sigset); 336 CHECK_EQ(sigprocmask_status, 0); // sigprocmask should never fail 337 // Make this process dumpable. Processes that are not dumpable cannot be 338 // attached to. 339 process_was_dumpable_ = internal_prctl(PR_GET_DUMPABLE, 0, 0, 0, 0); 340 if (!process_was_dumpable_) 341 internal_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); 342 old_die_callback = GetDieCallback(); 343 } 344 345 ~StopTheWorldScope() { 346 SetDieCallback(old_die_callback); 347 // Restore the dumpable flag. 348 if (!process_was_dumpable_) 349 internal_prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); 350 // Restore the signal handlers. 351 for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals); 352 signal_index++) { 353 sigaction(kUnblockedSignals[signal_index], 354 &old_sigactions[signal_index], NULL); 355 } 356 sigprocmask(SIG_SETMASK, &old_sigset, &old_sigset); 357 } 358 359 private: 360 int process_was_dumpable_; 361}; 362 363void StopTheWorld(StopTheWorldCallback callback, void *argument) { 364 StopTheWorldScope in_stoptheworld; 365 // Prepare the arguments for TracerThread. 366 struct TracerThreadArgument tracer_thread_argument; 367 tracer_thread_argument.callback = callback; 368 tracer_thread_argument.callback_argument = argument; 369 const uptr kTracerStackSize = 2 * 1024 * 1024; 370 ScopedStackSpaceWithGuard tracer_stack(kTracerStackSize); 371 // Block the execution of TracerThread until after we have set ptrace 372 // permissions. 373 tracer_thread_argument.mutex.Lock(); 374 pid_t tracer_pid = clone(TracerThread, tracer_stack.Bottom(), 375 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_UNTRACED, 376 &tracer_thread_argument); 377 if (tracer_pid < 0) { 378 Report("Failed spawning a tracer thread (errno %d).\n", errno); 379 tracer_thread_argument.mutex.Unlock(); 380 } else { 381 // On some systems we have to explicitly declare that we want to be traced 382 // by the tracer thread. 383#ifdef PR_SET_PTRACER 384 internal_prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0); 385#endif 386 // Allow the tracer thread to start. 387 tracer_thread_argument.mutex.Unlock(); 388 // Since errno is shared between this thread and the tracer thread, we 389 // must avoid using errno while the tracer thread is running. 390 // At this point, any signal will either be blocked or kill us, so waitpid 391 // should never return (and set errno) while the tracer thread is alive. 392 uptr waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL); 393 int wperrno; 394 if (internal_iserror(waitpid_status, &wperrno)) 395 Report("Waiting on the tracer thread failed (errno %d).\n", wperrno); 396 } 397} 398 399// Platform-specific methods from SuspendedThreadsList. 400#if SANITIZER_ANDROID && defined(__arm__) 401typedef pt_regs regs_struct; 402#define REG_SP ARM_sp 403 404#elif SANITIZER_LINUX && defined(__arm__) 405typedef user_regs regs_struct; 406#define REG_SP uregs[13] 407 408#elif defined(__i386__) || defined(__x86_64__) 409typedef user_regs_struct regs_struct; 410#if defined(__i386__) 411#define REG_SP esp 412#else 413#define REG_SP rsp 414#endif 415 416#elif defined(__powerpc__) || defined(__powerpc64__) 417typedef pt_regs regs_struct; 418#define REG_SP gpr[PT_R1] 419 420#elif defined(__mips__) 421typedef struct user regs_struct; 422#define REG_SP regs[EF_REG29] 423 424#else 425#error "Unsupported architecture" 426#endif // SANITIZER_ANDROID && defined(__arm__) 427 428int SuspendedThreadsList::GetRegistersAndSP(uptr index, 429 uptr *buffer, 430 uptr *sp) const { 431 pid_t tid = GetThreadID(index); 432 regs_struct regs; 433 int pterrno; 434 if (internal_iserror(internal_ptrace(PTRACE_GETREGS, tid, NULL, ®s), 435 &pterrno)) { 436 Report("Could not get registers from thread %d (errno %d).\n", 437 tid, pterrno); 438 return -1; 439 } 440 441 *sp = regs.REG_SP; 442 internal_memcpy(buffer, ®s, sizeof(regs)); 443 return 0; 444} 445 446uptr SuspendedThreadsList::RegisterCount() { 447 return sizeof(regs_struct) / sizeof(uptr); 448} 449} // namespace __sanitizer 450 451#endif // SANITIZER_LINUX 452