sanitizer_stoptheworld_linux_libcdep.cc revision d41fa1b7f2afe5dd78cd4e635e16fd5f079b0318
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 && defined(__x86_64__) 18 19#include "sanitizer_stoptheworld.h" 20 21#include <errno.h> 22#include <sched.h> // for CLONE_* definitions 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 75COMPILER_CHECK(sizeof(SuspendedThreadID) == sizeof(pid_t)); 76 77namespace __sanitizer { 78// This class handles thread suspending/unsuspending in the tracer thread. 79class ThreadSuspender { 80 public: 81 explicit ThreadSuspender(pid_t pid) 82 : pid_(pid) { 83 CHECK_GE(pid, 0); 84 } 85 bool SuspendAllThreads(); 86 void ResumeAllThreads(); 87 void KillAllThreads(); 88 SuspendedThreadsList &suspended_threads_list() { 89 return suspended_threads_list_; 90 } 91 private: 92 SuspendedThreadsList suspended_threads_list_; 93 pid_t pid_; 94 bool SuspendThread(SuspendedThreadID thread_id); 95}; 96 97bool ThreadSuspender::SuspendThread(SuspendedThreadID thread_id) { 98 // Are we already attached to this thread? 99 // Currently this check takes linear time, however the number of threads is 100 // usually small. 101 if (suspended_threads_list_.Contains(thread_id)) 102 return false; 103 int pterrno; 104 if (internal_iserror(internal_ptrace(PTRACE_ATTACH, thread_id, NULL, NULL), 105 &pterrno)) { 106 // Either the thread is dead, or something prevented us from attaching. 107 // Log this event and move on. 108 Report("Could not attach to thread %d (errno %d).\n", thread_id, pterrno); 109 return false; 110 } else { 111 if (SanitizerVerbosity > 0) 112 Report("Attached to thread %d.\n", thread_id); 113 // The thread is not guaranteed to stop before ptrace returns, so we must 114 // wait on it. 115 uptr waitpid_status; 116 HANDLE_EINTR(waitpid_status, internal_waitpid(thread_id, NULL, __WALL)); 117 int wperrno; 118 if (internal_iserror(waitpid_status, &wperrno)) { 119 // Got a ECHILD error. I don't think this situation is possible, but it 120 // doesn't hurt to report it. 121 Report("Waiting on thread %d failed, detaching (errno %d).\n", thread_id, 122 wperrno); 123 internal_ptrace(PTRACE_DETACH, thread_id, NULL, NULL); 124 return false; 125 } 126 suspended_threads_list_.Append(thread_id); 127 return true; 128 } 129} 130 131void ThreadSuspender::ResumeAllThreads() { 132 for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) { 133 pid_t tid = suspended_threads_list_.GetThreadID(i); 134 int pterrno; 135 if (!internal_iserror(internal_ptrace(PTRACE_DETACH, tid, NULL, NULL), 136 &pterrno)) { 137 if (SanitizerVerbosity > 0) 138 Report("Detached from thread %d.\n", tid); 139 } else { 140 // Either the thread is dead, or we are already detached. 141 // The latter case is possible, for instance, if this function was called 142 // from a signal handler. 143 Report("Could not detach from thread %d (errno %d).\n", tid, pterrno); 144 } 145 } 146} 147 148void ThreadSuspender::KillAllThreads() { 149 for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) 150 internal_ptrace(PTRACE_KILL, suspended_threads_list_.GetThreadID(i), 151 NULL, NULL); 152} 153 154bool ThreadSuspender::SuspendAllThreads() { 155 ThreadLister thread_lister(pid_); 156 bool added_threads; 157 do { 158 // Run through the directory entries once. 159 added_threads = false; 160 pid_t tid = thread_lister.GetNextTID(); 161 while (tid >= 0) { 162 if (SuspendThread(tid)) 163 added_threads = true; 164 tid = thread_lister.GetNextTID(); 165 } 166 if (thread_lister.error()) { 167 // Detach threads and fail. 168 ResumeAllThreads(); 169 return false; 170 } 171 thread_lister.Reset(); 172 } while (added_threads); 173 return true; 174} 175 176// Pointer to the ThreadSuspender instance for use in signal handler. 177static ThreadSuspender *thread_suspender_instance = NULL; 178 179// Signals that should not be blocked (this is used in the parent thread as well 180// as the tracer thread). 181static const int kUnblockedSignals[] = { SIGABRT, SIGILL, SIGFPE, SIGSEGV, 182 SIGBUS, SIGXCPU, SIGXFSZ }; 183 184// Structure for passing arguments into the tracer thread. 185struct TracerThreadArgument { 186 StopTheWorldCallback callback; 187 void *callback_argument; 188 // The tracer thread waits on this mutex while the parent finishes its 189 // preparations. 190 BlockingMutex mutex; 191 uptr parent_pid; 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 internal_prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); 229 // Check if parent is already dead. 230 if (internal_getppid() != tracer_thread_argument->parent_pid) 231 internal__exit(4); 232 233 // Wait for the parent thread to finish preparations. 234 tracer_thread_argument->mutex.Lock(); 235 tracer_thread_argument->mutex.Unlock(); 236 237 SetDieCallback(TracerThreadDieCallback); 238 239 ThreadSuspender thread_suspender(internal_getppid()); 240 // Global pointer for the signal handler. 241 thread_suspender_instance = &thread_suspender; 242 243 // Alternate stack for signal handling. 244 InternalScopedBuffer<char> handler_stack_memory(kHandlerStackSize); 245 struct sigaltstack handler_stack; 246 internal_memset(&handler_stack, 0, sizeof(handler_stack)); 247 handler_stack.ss_sp = handler_stack_memory.data(); 248 handler_stack.ss_size = kHandlerStackSize; 249 internal_sigaltstack(&handler_stack, NULL); 250 251 // Install our handler for fatal signals. Other signals should be blocked by 252 // the mask we inherited from the caller thread. 253 for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals); 254 signal_index++) { 255 struct sigaction new_sigaction; 256 internal_memset(&new_sigaction, 0, sizeof(new_sigaction)); 257 new_sigaction.sa_sigaction = TracerThreadSignalHandler; 258 new_sigaction.sa_flags = SA_ONSTACK | SA_SIGINFO; 259 sigfillset(&new_sigaction.sa_mask); 260 sigaction(kUnblockedSignals[signal_index], &new_sigaction, NULL); 261 } 262 263 int exit_code = 0; 264 if (!thread_suspender.SuspendAllThreads()) { 265 Report("Failed suspending threads.\n"); 266 exit_code = 3; 267 } else { 268 tracer_thread_argument->callback(thread_suspender.suspended_threads_list(), 269 tracer_thread_argument->callback_argument); 270 thread_suspender.ResumeAllThreads(); 271 exit_code = 0; 272 } 273 thread_suspender_instance = NULL; 274 handler_stack.ss_flags = SS_DISABLE; 275 internal_sigaltstack(&handler_stack, NULL); 276 return exit_code; 277} 278 279class ScopedStackSpaceWithGuard { 280 public: 281 explicit ScopedStackSpaceWithGuard(uptr stack_size) { 282 stack_size_ = stack_size; 283 guard_size_ = GetPageSizeCached(); 284 // FIXME: Omitting MAP_STACK here works in current kernels but might break 285 // in the future. 286 guard_start_ = (uptr)MmapOrDie(stack_size_ + guard_size_, 287 "ScopedStackWithGuard"); 288 CHECK_EQ(guard_start_, (uptr)Mprotect((uptr)guard_start_, guard_size_)); 289 } 290 ~ScopedStackSpaceWithGuard() { 291 UnmapOrDie((void *)guard_start_, stack_size_ + guard_size_); 292 } 293 void *Bottom() const { 294 return (void *)(guard_start_ + stack_size_ + guard_size_); 295 } 296 297 private: 298 uptr stack_size_; 299 uptr guard_size_; 300 uptr guard_start_; 301}; 302 303NOINLINE static void WipeStack() { 304 char arr[256]; 305 internal_memset(arr, 0, sizeof(arr)); 306} 307 308// We have a limitation on the stack frame size, so some stuff had to be moved 309// into globals. 310static sigset_t blocked_sigset; 311static sigset_t old_sigset; 312static struct sigaction old_sigactions[ARRAY_SIZE(kUnblockedSignals)]; 313 314class StopTheWorldScope { 315 public: 316 StopTheWorldScope() { 317 // Glibc's sigaction() has a side-effect where it copies garbage stack 318 // values into oldact, which can cause false negatives in LSan. As a quick 319 // workaround we zero some stack space here. 320 WipeStack(); 321 // Block all signals that can be blocked safely, and install 322 // default handlers for the remaining signals. 323 // We cannot allow user-defined handlers to run while the ThreadSuspender 324 // thread is active, because they could conceivably call some libc functions 325 // which modify errno (which is shared between the two threads). 326 sigfillset(&blocked_sigset); 327 for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals); 328 signal_index++) { 329 // Remove the signal from the set of blocked signals. 330 sigdelset(&blocked_sigset, kUnblockedSignals[signal_index]); 331 // Install the default handler. 332 struct sigaction new_sigaction; 333 internal_memset(&new_sigaction, 0, sizeof(new_sigaction)); 334 new_sigaction.sa_handler = SIG_DFL; 335 sigfillset(&new_sigaction.sa_mask); 336 sigaction(kUnblockedSignals[signal_index], &new_sigaction, 337 &old_sigactions[signal_index]); 338 } 339 int sigprocmask_status = 340 sigprocmask(SIG_BLOCK, &blocked_sigset, &old_sigset); 341 CHECK_EQ(sigprocmask_status, 0); // sigprocmask should never fail 342 // Make this process dumpable. Processes that are not dumpable cannot be 343 // attached to. 344 process_was_dumpable_ = internal_prctl(PR_GET_DUMPABLE, 0, 0, 0, 0); 345 if (!process_was_dumpable_) 346 internal_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); 347 old_die_callback = GetDieCallback(); 348 } 349 350 ~StopTheWorldScope() { 351 SetDieCallback(old_die_callback); 352 // Restore the dumpable flag. 353 if (!process_was_dumpable_) 354 internal_prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); 355 // Restore the signal handlers. 356 for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals); 357 signal_index++) { 358 sigaction(kUnblockedSignals[signal_index], 359 &old_sigactions[signal_index], NULL); 360 } 361 sigprocmask(SIG_SETMASK, &old_sigset, &old_sigset); 362 } 363 364 private: 365 int process_was_dumpable_; 366}; 367 368void StopTheWorld(StopTheWorldCallback callback, void *argument) { 369 StopTheWorldScope in_stoptheworld; 370 // Prepare the arguments for TracerThread. 371 struct TracerThreadArgument tracer_thread_argument; 372 tracer_thread_argument.callback = callback; 373 tracer_thread_argument.callback_argument = argument; 374 tracer_thread_argument.parent_pid = internal_getpid(); 375 const uptr kTracerStackSize = 2 * 1024 * 1024; 376 ScopedStackSpaceWithGuard tracer_stack(kTracerStackSize); 377 // Block the execution of TracerThread until after we have set ptrace 378 // permissions. 379 tracer_thread_argument.mutex.Lock(); 380 uptr tracer_pid = internal_clone( 381 TracerThread, tracer_stack.Bottom(), 382 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_UNTRACED, 383 &tracer_thread_argument, 0 /* parent_tidptr */, 0 /* newtls */, 0 384 /* child_tidptr */); 385 int local_errno = 0; 386 if (internal_iserror(tracer_pid, &local_errno)) { 387 Report("Failed spawning a tracer thread (errno %d).\n", local_errno); 388 tracer_thread_argument.mutex.Unlock(); 389 } else { 390 // On some systems we have to explicitly declare that we want to be traced 391 // by the tracer thread. 392#ifdef PR_SET_PTRACER 393 internal_prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0); 394#endif 395 // Allow the tracer thread to start. 396 tracer_thread_argument.mutex.Unlock(); 397 // Since errno is shared between this thread and the tracer thread, we 398 // must avoid using errno while the tracer thread is running. 399 // At this point, any signal will either be blocked or kill us, so waitpid 400 // should never return (and set errno) while the tracer thread is alive. 401 uptr waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL); 402 if (internal_iserror(waitpid_status, &local_errno)) 403 Report("Waiting on the tracer thread failed (errno %d).\n", local_errno); 404 } 405} 406 407// Platform-specific methods from SuspendedThreadsList. 408#if SANITIZER_ANDROID && defined(__arm__) 409typedef pt_regs regs_struct; 410#define REG_SP ARM_sp 411 412#elif SANITIZER_LINUX && defined(__arm__) 413typedef user_regs regs_struct; 414#define REG_SP uregs[13] 415 416#elif defined(__i386__) || defined(__x86_64__) 417typedef user_regs_struct regs_struct; 418#if defined(__i386__) 419#define REG_SP esp 420#else 421#define REG_SP rsp 422#endif 423 424#elif defined(__powerpc__) || defined(__powerpc64__) 425typedef pt_regs regs_struct; 426#define REG_SP gpr[PT_R1] 427 428#elif defined(__mips__) 429typedef struct user regs_struct; 430#define REG_SP regs[EF_REG29] 431 432#else 433#error "Unsupported architecture" 434#endif // SANITIZER_ANDROID && defined(__arm__) 435 436int SuspendedThreadsList::GetRegistersAndSP(uptr index, 437 uptr *buffer, 438 uptr *sp) const { 439 pid_t tid = GetThreadID(index); 440 regs_struct regs; 441 int pterrno; 442 if (internal_iserror(internal_ptrace(PTRACE_GETREGS, tid, NULL, ®s), 443 &pterrno)) { 444 Report("Could not get registers from thread %d (errno %d).\n", 445 tid, pterrno); 446 return -1; 447 } 448 449 *sp = regs.REG_SP; 450 internal_memcpy(buffer, ®s, sizeof(regs)); 451 return 0; 452} 453 454uptr SuspendedThreadsList::RegisterCount() { 455 return sizeof(regs_struct) / sizeof(uptr); 456} 457} // namespace __sanitizer 458 459#endif // SANITIZER_LINUX && defined(__x86_64__) 460