1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "client/crashpad_client.h"
16 
17 #include <windows.h>
18 
19 #include <signal.h>
20 #include <stdint.h>
21 #include <string.h>
22 
23 #include <memory>
24 
25 #include "base/atomicops.h"
26 #include "base/logging.h"
27 #include "base/macros.h"
28 #include "base/scoped_generic.h"
29 #include "base/strings/string16.h"
30 #include "base/strings/stringprintf.h"
31 #include "base/strings/utf_string_conversions.h"
32 #include "base/synchronization/lock.h"
33 #include "util/file/file_io.h"
34 #include "util/misc/capture_context.h"
35 #include "util/misc/from_pointer_cast.h"
36 #include "util/misc/random_string.h"
37 #include "util/win/address_types.h"
38 #include "util/win/command_line.h"
39 #include "util/win/context_wrappers.h"
40 #include "util/win/critical_section_with_debug_info.h"
41 #include "util/win/get_function.h"
42 #include "util/win/handle.h"
43 #include "util/win/initial_client_data.h"
44 #include "util/win/loader_lock.h"
45 #include "util/win/nt_internals.h"
46 #include "util/win/ntstatus_logging.h"
47 #include "util/win/process_info.h"
48 #include "util/win/registration_protocol_win.h"
49 #include "util/win/safe_terminate_process.h"
50 #include "util/win/scoped_process_suspend.h"
51 #include "util/win/termination_codes.h"
52 #include "util/win/xp_compat.h"
53 
54 namespace crashpad {
55 
56 namespace {
57 
58 // This handle is never closed. This is used to signal to the server that a dump
59 // should be taken in the event of a crash.
60 HANDLE g_signal_exception = INVALID_HANDLE_VALUE;
61 
62 // Where we store the exception information that the crash handler reads.
63 ExceptionInformation g_crash_exception_information;
64 
65 // These handles are never closed. g_signal_non_crash_dump is used to signal to
66 // the server to take a dump (not due to an exception), and the server will
67 // signal g_non_crash_dump_done when the dump is completed.
68 HANDLE g_signal_non_crash_dump = INVALID_HANDLE_VALUE;
69 HANDLE g_non_crash_dump_done = INVALID_HANDLE_VALUE;
70 
71 // Guards multiple simultaneous calls to DumpWithoutCrash(). This is leaked.
72 base::Lock* g_non_crash_dump_lock;
73 
74 // Where we store a pointer to the context information when taking a non-crash
75 // dump.
76 ExceptionInformation g_non_crash_exception_information;
77 
78 enum class StartupState : int {
79   kNotReady = 0,  // This must be value 0 because it is the initial value of a
80                   // global AtomicWord.
81   kSucceeded = 1,  // The CreateProcess() for the handler succeeded.
82   kFailed = 2,  // The handler failed to start.
83 };
84 
85 // This is a tri-state of type StartupState. It starts at 0 == kNotReady, and
86 // when the handler is known to have started successfully, or failed to start
87 // the value will be updated. The unhandled exception filter will not proceed
88 // until one of those two cases happens.
89 base::subtle::AtomicWord g_handler_startup_state;
90 
91 // A CRITICAL_SECTION initialized with
92 // RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO to force it to be allocated with a
93 // valid .DebugInfo field. The address of this critical section is given to the
94 // handler. All critical sections with debug info are linked in a doubly-linked
95 // list, so this allows the handler to capture all of them.
96 CRITICAL_SECTION g_critical_section_with_debug_info;
97 
SetHandlerStartupState(StartupState state)98 void SetHandlerStartupState(StartupState state) {
99   DCHECK(state == StartupState::kSucceeded || state == StartupState::kFailed);
100   base::subtle::Release_Store(&g_handler_startup_state,
101                               static_cast<base::subtle::AtomicWord>(state));
102 }
103 
BlockUntilHandlerStartedOrFailed()104 StartupState BlockUntilHandlerStartedOrFailed() {
105   // Wait until we know the handler has either succeeded or failed to start.
106   base::subtle::AtomicWord startup_state;
107   while (
108       (startup_state = base::subtle::Acquire_Load(&g_handler_startup_state)) ==
109       static_cast<int>(StartupState::kNotReady)) {
110     Sleep(1);
111   }
112 
113   return static_cast<StartupState>(startup_state);
114 }
115 
116 #if defined(ADDRESS_SANITIZER)
117 extern "C" LONG __asan_unhandled_exception_filter(EXCEPTION_POINTERS* info);
118 #endif
119 
UnhandledExceptionHandler(EXCEPTION_POINTERS * exception_pointers)120 LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) {
121 #if defined(ADDRESS_SANITIZER)
122   // In ASan builds, delegate to the ASan exception filter.
123   LONG status = __asan_unhandled_exception_filter(exception_pointers);
124   if (status != EXCEPTION_CONTINUE_SEARCH)
125     return status;
126 #endif
127 
128   if (BlockUntilHandlerStartedOrFailed() == StartupState::kFailed) {
129     // If we know for certain that the handler has failed to start, then abort
130     // here, rather than trying to signal to a handler that will never arrive,
131     // and then sleeping unnecessarily.
132     LOG(ERROR) << "crash server failed to launch, self-terminating";
133     SafeTerminateProcess(GetCurrentProcess(), kTerminationCodeCrashNoDump);
134     return EXCEPTION_CONTINUE_SEARCH;
135   }
136 
137   // Otherwise, we know the handler startup has succeeded, and we can continue.
138 
139   // Tracks whether a thread has already entered UnhandledExceptionHandler.
140   static base::subtle::AtomicWord have_crashed;
141 
142   // This is a per-process handler. While this handler is being invoked, other
143   // threads are still executing as usual, so multiple threads could enter at
144   // the same time. Because we're in a crashing state, we shouldn't be doing
145   // anything that might cause allocations, call into kernel mode, etc. So, we
146   // don't want to take a critical section here to avoid simultaneous access to
147   // the global exception pointers in ExceptionInformation. Because the crash
148   // handler will record all threads, it's fine to simply have the second and
149   // subsequent entrants block here. They will soon be suspended by the crash
150   // handler, and then the entire process will be terminated below. This means
151   // that we won't save the exception pointers from the second and further
152   // crashes, but contention here is very unlikely, and we'll still have a stack
153   // that's blocked at this location.
154   if (base::subtle::Barrier_AtomicIncrement(&have_crashed, 1) > 1) {
155     SleepEx(INFINITE, false);
156   }
157 
158   // Otherwise, we're the first thread, so record the exception pointer and
159   // signal the crash handler.
160   g_crash_exception_information.thread_id = GetCurrentThreadId();
161   g_crash_exception_information.exception_pointers =
162       FromPointerCast<WinVMAddress>(exception_pointers);
163 
164   // Now signal the crash server, which will take a dump and then terminate us
165   // when it's complete.
166   SetEvent(g_signal_exception);
167 
168   // Time to wait for the handler to create a dump.
169   constexpr DWORD kMillisecondsUntilTerminate = 60 * 1000;
170 
171   // Sleep for a while to allow it to process us. Eventually, we terminate
172   // ourselves in case the crash server is gone, so that we don't leave zombies
173   // around. This would ideally never happen.
174   Sleep(kMillisecondsUntilTerminate);
175 
176   LOG(ERROR) << "crash server did not respond, self-terminating";
177 
178   SafeTerminateProcess(GetCurrentProcess(), kTerminationCodeCrashNoDump);
179 
180   return EXCEPTION_CONTINUE_SEARCH;
181 }
182 
HandleAbortSignal(int signum)183 void HandleAbortSignal(int signum) {
184   DCHECK_EQ(signum, SIGABRT);
185 
186   CONTEXT context;
187   CaptureContext(&context);
188 
189   EXCEPTION_RECORD record = {};
190   record.ExceptionCode = STATUS_FATAL_APP_EXIT;
191   record.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
192   record.ExceptionAddress = ProgramCounterFromCONTEXT(&context);
193 
194   EXCEPTION_POINTERS exception_pointers;
195   exception_pointers.ContextRecord = &context;
196   exception_pointers.ExceptionRecord = &record;
197 
198   UnhandledExceptionHandler(&exception_pointers);
199 }
200 
FormatArgumentString(const std::string & name,const std::wstring & value)201 std::wstring FormatArgumentString(const std::string& name,
202                                   const std::wstring& value) {
203   return std::wstring(L"--") + base::UTF8ToUTF16(name) + L"=" + value;
204 }
205 
206 struct ScopedProcThreadAttributeListTraits {
InvalidValuecrashpad::__anon2605ad160111::ScopedProcThreadAttributeListTraits207   static PPROC_THREAD_ATTRIBUTE_LIST InvalidValue() { return nullptr; }
208 
Freecrashpad::__anon2605ad160111::ScopedProcThreadAttributeListTraits209   static void Free(PPROC_THREAD_ATTRIBUTE_LIST proc_thread_attribute_list) {
210     // This is able to use GET_FUNCTION_REQUIRED() instead of GET_FUNCTION()
211     // because it will only be called if InitializeProcThreadAttributeList() and
212     // UpdateProcThreadAttribute() are present.
213     static const auto delete_proc_thread_attribute_list =
214         GET_FUNCTION_REQUIRED(L"kernel32.dll", ::DeleteProcThreadAttributeList);
215     delete_proc_thread_attribute_list(proc_thread_attribute_list);
216   }
217 };
218 
219 using ScopedProcThreadAttributeList =
220     base::ScopedGeneric<PPROC_THREAD_ATTRIBUTE_LIST,
221                         ScopedProcThreadAttributeListTraits>;
222 
IsInheritableHandle(HANDLE handle)223 bool IsInheritableHandle(HANDLE handle) {
224   if (!handle || handle == INVALID_HANDLE_VALUE)
225     return false;
226 
227   // File handles (FILE_TYPE_DISK) and pipe handles (FILE_TYPE_PIPE) are known
228   // to be inheritable. Console handles (FILE_TYPE_CHAR) are not inheritable via
229   // PROC_THREAD_ATTRIBUTE_HANDLE_LIST. See
230   // https://crashpad.chromium.org/bug/77.
231   DWORD handle_type = GetFileType(handle);
232   return handle_type == FILE_TYPE_DISK || handle_type == FILE_TYPE_PIPE;
233 }
234 
235 // Adds |handle| to |handle_list| if it appears valid, and is not already in
236 // |handle_list|.
237 //
238 // Invalid handles (including INVALID_HANDLE_VALUE and null handles) cannot be
239 // added to a PPROC_THREAD_ATTRIBUTE_LIST’s PROC_THREAD_ATTRIBUTE_HANDLE_LIST.
240 // If INVALID_HANDLE_VALUE appears, CreateProcess() will fail with
241 // ERROR_INVALID_PARAMETER. If a null handle appears, the child process will
242 // silently not inherit any handles.
243 //
244 // Use this function to add handles with uncertain validities.
AddHandleToListIfValidAndInheritable(std::vector<HANDLE> * handle_list,HANDLE handle)245 void AddHandleToListIfValidAndInheritable(std::vector<HANDLE>* handle_list,
246                                           HANDLE handle) {
247   // There doesn't seem to be any documentation of this, but if there's a handle
248   // duplicated in this list, CreateProcess() fails with
249   // ERROR_INVALID_PARAMETER.
250   if (IsInheritableHandle(handle) &&
251       std::find(handle_list->begin(), handle_list->end(), handle) ==
252           handle_list->end()) {
253     handle_list->push_back(handle);
254   }
255 }
256 
AddUint32(std::vector<unsigned char> * data_vector,uint32_t data)257 void AddUint32(std::vector<unsigned char>* data_vector, uint32_t data) {
258   data_vector->push_back(static_cast<unsigned char>(data & 0xff));
259   data_vector->push_back(static_cast<unsigned char>((data & 0xff00) >> 8));
260   data_vector->push_back(static_cast<unsigned char>((data & 0xff0000) >> 16));
261   data_vector->push_back(static_cast<unsigned char>((data & 0xff000000) >> 24));
262 }
263 
AddUint64(std::vector<unsigned char> * data_vector,uint64_t data)264 void AddUint64(std::vector<unsigned char>* data_vector, uint64_t data) {
265   AddUint32(data_vector, static_cast<uint32_t>(data & 0xffffffffULL));
266   AddUint32(data_vector,
267             static_cast<uint32_t>((data & 0xffffffff00000000ULL) >> 32));
268 }
269 
270 //! \brief Creates a randomized pipe name to listen for client registrations
271 //!     on and returns its name.
272 //!
273 //! \param[out] pipe_name The pipe name that will be listened on.
274 //! \param[out] pipe_handle The first pipe instance corresponding for the pipe.
CreatePipe(std::wstring * pipe_name,ScopedFileHANDLE * pipe_instance)275 void CreatePipe(std::wstring* pipe_name, ScopedFileHANDLE* pipe_instance) {
276   int tries = 5;
277   std::string pipe_name_base =
278       base::StringPrintf("\\\\.\\pipe\\crashpad_%lu_", GetCurrentProcessId());
279   do {
280     *pipe_name = base::UTF8ToUTF16(pipe_name_base + RandomString());
281 
282     pipe_instance->reset(CreateNamedPipeInstance(*pipe_name, true));
283 
284     // CreateNamedPipe() is documented as setting the error to
285     // ERROR_ACCESS_DENIED if FILE_FLAG_FIRST_PIPE_INSTANCE is specified and the
286     // pipe name is already in use. However it may set the error to other codes
287     // such as ERROR_PIPE_BUSY (if the pipe already exists and has reached its
288     // maximum instance count) or ERROR_INVALID_PARAMETER (if the pipe already
289     // exists and its attributes differ from those specified to
290     // CreateNamedPipe()). Some of these errors may be ambiguous: for example,
291     // ERROR_INVALID_PARAMETER may also occur if CreateNamedPipe() is called
292     // incorrectly even in the absence of an existing pipe by the same name.
293     // Rather than chasing down all of the possible errors that might indicate
294     // that a pipe name is already in use, retry up to a few times on any error.
295   } while (!pipe_instance->is_valid() && --tries);
296 
297   PCHECK(pipe_instance->is_valid()) << "CreateNamedPipe";
298 }
299 
300 struct BackgroundHandlerStartThreadData {
BackgroundHandlerStartThreadDatacrashpad::__anon2605ad160111::BackgroundHandlerStartThreadData301   BackgroundHandlerStartThreadData(
302       const base::FilePath& handler,
303       const base::FilePath& database,
304       const base::FilePath& metrics_dir,
305       const std::string& url,
306       const std::map<std::string, std::string>& annotations,
307       const std::vector<std::string>& arguments,
308       const std::wstring& ipc_pipe,
309       ScopedFileHANDLE ipc_pipe_handle)
310       : handler(handler),
311         database(database),
312         metrics_dir(metrics_dir),
313         url(url),
314         annotations(annotations),
315         arguments(arguments),
316         ipc_pipe(ipc_pipe),
317         ipc_pipe_handle(std::move(ipc_pipe_handle)) {}
318 
319   base::FilePath handler;
320   base::FilePath database;
321   base::FilePath metrics_dir;
322   std::string url;
323   std::map<std::string, std::string> annotations;
324   std::vector<std::string> arguments;
325   std::wstring ipc_pipe;
326   ScopedFileHANDLE ipc_pipe_handle;
327 };
328 
329 // Ensures that SetHandlerStartupState() is called on scope exit. Assumes
330 // failure, and on success, SetSuccessful() should be called.
331 class ScopedCallSetHandlerStartupState {
332  public:
ScopedCallSetHandlerStartupState()333   ScopedCallSetHandlerStartupState() : successful_(false) {}
334 
~ScopedCallSetHandlerStartupState()335   ~ScopedCallSetHandlerStartupState() {
336     SetHandlerStartupState(successful_ ? StartupState::kSucceeded
337                                        : StartupState::kFailed);
338   }
339 
SetSuccessful()340   void SetSuccessful() { successful_ = true; }
341 
342  private:
343   bool successful_;
344 
345   DISALLOW_COPY_AND_ASSIGN(ScopedCallSetHandlerStartupState);
346 };
347 
StartHandlerProcess(std::unique_ptr<BackgroundHandlerStartThreadData> data)348 bool StartHandlerProcess(
349     std::unique_ptr<BackgroundHandlerStartThreadData> data) {
350   CHECK(!IsThreadInLoaderLock());
351 
352   ScopedCallSetHandlerStartupState scoped_startup_state_caller;
353 
354   std::wstring command_line;
355   AppendCommandLineArgument(data->handler.value(), &command_line);
356   for (const std::string& argument : data->arguments) {
357     AppendCommandLineArgument(base::UTF8ToUTF16(argument), &command_line);
358   }
359   if (!data->database.value().empty()) {
360     AppendCommandLineArgument(
361         FormatArgumentString("database", data->database.value()),
362         &command_line);
363   }
364   if (!data->metrics_dir.value().empty()) {
365     AppendCommandLineArgument(
366         FormatArgumentString("metrics-dir", data->metrics_dir.value()),
367         &command_line);
368   }
369   if (!data->url.empty()) {
370     AppendCommandLineArgument(
371         FormatArgumentString("url", base::UTF8ToUTF16(data->url)),
372         &command_line);
373   }
374   for (const auto& kv : data->annotations) {
375     AppendCommandLineArgument(
376         FormatArgumentString("annotation",
377                              base::UTF8ToUTF16(kv.first + '=' + kv.second)),
378         &command_line);
379   }
380 
381   ScopedKernelHANDLE this_process(
382       OpenProcess(kXPProcessAllAccess, true, GetCurrentProcessId()));
383   if (!this_process.is_valid()) {
384     PLOG(ERROR) << "OpenProcess";
385     return false;
386   }
387 
388   InitialClientData initial_client_data(
389       g_signal_exception,
390       g_signal_non_crash_dump,
391       g_non_crash_dump_done,
392       data->ipc_pipe_handle.get(),
393       this_process.get(),
394       FromPointerCast<WinVMAddress>(&g_crash_exception_information),
395       FromPointerCast<WinVMAddress>(&g_non_crash_exception_information),
396       FromPointerCast<WinVMAddress>(&g_critical_section_with_debug_info));
397   AppendCommandLineArgument(
398       base::UTF8ToUTF16(std::string("--initial-client-data=") +
399                         initial_client_data.StringRepresentation()),
400       &command_line);
401 
402   BOOL rv;
403   DWORD creation_flags;
404   STARTUPINFOEX startup_info = {};
405   startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
406   startup_info.StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
407   startup_info.StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
408   startup_info.StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
409 
410   std::vector<HANDLE> handle_list;
411   std::unique_ptr<uint8_t[]> proc_thread_attribute_list_storage;
412   ScopedProcThreadAttributeList proc_thread_attribute_list_owner;
413 
414   static const auto initialize_proc_thread_attribute_list =
415       GET_FUNCTION(L"kernel32.dll", ::InitializeProcThreadAttributeList);
416   static const auto update_proc_thread_attribute =
417       initialize_proc_thread_attribute_list
418           ? GET_FUNCTION(L"kernel32.dll", ::UpdateProcThreadAttribute)
419           : nullptr;
420   if (!initialize_proc_thread_attribute_list || !update_proc_thread_attribute) {
421     // The OS doesn’t allow handle inheritance to be restricted, so the handler
422     // will inherit every inheritable handle.
423     creation_flags = 0;
424     startup_info.StartupInfo.cb = sizeof(startup_info.StartupInfo);
425   } else {
426     // Restrict handle inheritance to just those needed in the handler.
427 
428     creation_flags = EXTENDED_STARTUPINFO_PRESENT;
429     startup_info.StartupInfo.cb = sizeof(startup_info);
430     SIZE_T size;
431     rv = initialize_proc_thread_attribute_list(nullptr, 1, 0, &size);
432     if (rv) {
433       LOG(ERROR) << "InitializeProcThreadAttributeList (size) succeeded, "
434                     "expected failure";
435       return false;
436     } else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
437       PLOG(ERROR) << "InitializeProcThreadAttributeList (size)";
438       return false;
439     }
440 
441     proc_thread_attribute_list_storage.reset(new uint8_t[size]);
442     startup_info.lpAttributeList =
443         reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(
444             proc_thread_attribute_list_storage.get());
445     rv = initialize_proc_thread_attribute_list(
446         startup_info.lpAttributeList, 1, 0, &size);
447     if (!rv) {
448       PLOG(ERROR) << "InitializeProcThreadAttributeList";
449       return false;
450     }
451     proc_thread_attribute_list_owner.reset(startup_info.lpAttributeList);
452 
453     handle_list.reserve(8);
454     handle_list.push_back(g_signal_exception);
455     handle_list.push_back(g_signal_non_crash_dump);
456     handle_list.push_back(g_non_crash_dump_done);
457     handle_list.push_back(data->ipc_pipe_handle.get());
458     handle_list.push_back(this_process.get());
459     AddHandleToListIfValidAndInheritable(&handle_list,
460                                          startup_info.StartupInfo.hStdInput);
461     AddHandleToListIfValidAndInheritable(&handle_list,
462                                          startup_info.StartupInfo.hStdOutput);
463     AddHandleToListIfValidAndInheritable(&handle_list,
464                                          startup_info.StartupInfo.hStdError);
465     rv = update_proc_thread_attribute(
466         startup_info.lpAttributeList,
467         0,
468         PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
469         &handle_list[0],
470         handle_list.size() * sizeof(handle_list[0]),
471         nullptr,
472         nullptr);
473     if (!rv) {
474       PLOG(ERROR) << "UpdateProcThreadAttribute";
475       return false;
476     }
477   }
478 
479   // If the embedded crashpad handler is being started via an entry point in a
480   // DLL (the handler executable is rundll32.exe), then don't pass
481   // the application name to CreateProcess as this appears to generate an
482   // invalid command line where the first argument needed by rundll32 is not in
483   // the correct format as required in:
484   // https://support.microsoft.com/en-ca/help/164787/info-windows-rundll-and-rundll32-interface
485   const base::StringPiece16 kRunDll32Exe(L"rundll32.exe");
486   bool is_embedded_in_dll = false;
487   if (data->handler.value().size() >= kRunDll32Exe.size() &&
488       _wcsicmp(data->handler.value()
489                    .substr(data->handler.value().size() - kRunDll32Exe.size())
490                    .c_str(),
491                kRunDll32Exe.data()) == 0) {
492     is_embedded_in_dll = true;
493   }
494 
495   PROCESS_INFORMATION process_info;
496   rv = CreateProcess(
497       is_embedded_in_dll ? nullptr : data->handler.value().c_str(),
498       &command_line[0],
499       nullptr,
500       nullptr,
501       true,
502       creation_flags,
503       nullptr,
504       nullptr,
505       &startup_info.StartupInfo,
506       &process_info);
507   if (!rv) {
508     PLOG(ERROR) << "CreateProcess";
509     return false;
510   }
511 
512   rv = CloseHandle(process_info.hThread);
513   PLOG_IF(WARNING, !rv) << "CloseHandle thread";
514 
515   rv = CloseHandle(process_info.hProcess);
516   PLOG_IF(WARNING, !rv) << "CloseHandle process";
517 
518   // It is important to close our side of the pipe here before confirming that
519   // we can communicate with the server. By doing so, the only remaining copy of
520   // the server side of the pipe belongs to the exception handler process we
521   // just spawned. Otherwise, the pipe will continue to exist indefinitely, so
522   // the connection loop will not detect that it will never be serviced.
523   data->ipc_pipe_handle.reset();
524 
525   // Confirm that the server is waiting for connections before continuing.
526   ClientToServerMessage message = {};
527   message.type = ClientToServerMessage::kPing;
528   ServerToClientMessage response = {};
529   if (!SendToCrashHandlerServer(data->ipc_pipe, message, &response)) {
530     return false;
531   }
532 
533   scoped_startup_state_caller.SetSuccessful();
534   return true;
535 }
536 
BackgroundHandlerStartThreadProc(void * data)537 DWORD WINAPI BackgroundHandlerStartThreadProc(void* data) {
538   std::unique_ptr<BackgroundHandlerStartThreadData> data_as_ptr(
539       reinterpret_cast<BackgroundHandlerStartThreadData*>(data));
540   return StartHandlerProcess(std::move(data_as_ptr)) ? 0 : 1;
541 }
542 
CommonInProcessInitialization()543 void CommonInProcessInitialization() {
544   // We create this dummy CRITICAL_SECTION with the
545   // RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO flag set to have an entry point
546   // into the doubly-linked list of RTL_CRITICAL_SECTION_DEBUG objects. This
547   // allows us to walk the list at crash time to gather data for !locks. A
548   // debugger would instead inspect ntdll!RtlCriticalSectionList to get the head
549   // of the list. But that is not an exported symbol, so on an arbitrary client
550   // machine, we don't have a way of getting that pointer.
551   InitializeCriticalSectionWithDebugInfoIfPossible(
552       &g_critical_section_with_debug_info);
553 
554   g_non_crash_dump_lock = new base::Lock();
555 }
556 
RegisterHandlers()557 void RegisterHandlers() {
558   SetUnhandledExceptionFilter(&UnhandledExceptionHandler);
559 
560   // The Windows CRT's signal.h lists:
561   // - SIGINT
562   // - SIGILL
563   // - SIGFPE
564   // - SIGSEGV
565   // - SIGTERM
566   // - SIGBREAK
567   // - SIGABRT
568   // SIGILL and SIGTERM are documented as not being generated. SIGBREAK and
569   // SIGINT are for Ctrl-Break and Ctrl-C, and aren't something for which
570   // capturing a dump is warranted. SIGFPE and SIGSEGV are captured as regular
571   // exceptions through the unhandled exception filter. This leaves SIGABRT. In
572   // the standard CRT, abort() is implemented as a synchronous call to the
573   // SIGABRT signal handler if installed, but after doing so, the unhandled
574   // exception filter is not triggered (it instead __fastfail()s). So, register
575   // to handle SIGABRT to catch abort() calls, as client code might use this and
576   // expect it to cause a crash dump. This will only work when the abort()
577   // that's called in client code is the same (or has the same behavior) as the
578   // one in use here.
579   void (*rv)(int) = signal(SIGABRT, HandleAbortSignal);
580   DCHECK_NE(rv, SIG_ERR);
581 }
582 
583 }  // namespace
584 
CrashpadClient()585 CrashpadClient::CrashpadClient() : ipc_pipe_(), handler_start_thread_() {}
586 
~CrashpadClient()587 CrashpadClient::~CrashpadClient() {}
588 
StartHandler(const base::FilePath & handler,const base::FilePath & database,const base::FilePath & metrics_dir,const std::string & url,const std::map<std::string,std::string> & annotations,const std::vector<std::string> & arguments,bool restartable,bool asynchronous_start)589 bool CrashpadClient::StartHandler(
590     const base::FilePath& handler,
591     const base::FilePath& database,
592     const base::FilePath& metrics_dir,
593     const std::string& url,
594     const std::map<std::string, std::string>& annotations,
595     const std::vector<std::string>& arguments,
596     bool restartable,
597     bool asynchronous_start) {
598   DCHECK(ipc_pipe_.empty());
599 
600   // Both the pipe and the signalling events have to be created on the main
601   // thread (not the spawning thread) so that they're valid after we return from
602   // this function.
603   ScopedFileHANDLE ipc_pipe_handle;
604   CreatePipe(&ipc_pipe_, &ipc_pipe_handle);
605 
606   SECURITY_ATTRIBUTES security_attributes = {0};
607   security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
608   security_attributes.bInheritHandle = true;
609 
610   g_signal_exception =
611       CreateEvent(&security_attributes, false /* auto reset */, false, nullptr);
612   g_signal_non_crash_dump =
613       CreateEvent(&security_attributes, false /* auto reset */, false, nullptr);
614   g_non_crash_dump_done =
615       CreateEvent(&security_attributes, false /* auto reset */, false, nullptr);
616 
617   CommonInProcessInitialization();
618 
619   RegisterHandlers();
620 
621   auto data = new BackgroundHandlerStartThreadData(handler,
622                                                    database,
623                                                    metrics_dir,
624                                                    url,
625                                                    annotations,
626                                                    arguments,
627                                                    ipc_pipe_,
628                                                    std::move(ipc_pipe_handle));
629 
630   if (asynchronous_start) {
631     // It is important that the current thread not be synchronized with the
632     // thread that is created here. StartHandler() needs to be callable inside a
633     // DllMain(). In that case, the background thread will not start until the
634     // current DllMain() completes, which would cause deadlock if it was waited
635     // upon.
636     handler_start_thread_.reset(CreateThread(nullptr,
637                                              0,
638                                              &BackgroundHandlerStartThreadProc,
639                                              reinterpret_cast<void*>(data),
640                                              0,
641                                              nullptr));
642     if (!handler_start_thread_.is_valid()) {
643       PLOG(ERROR) << "CreateThread";
644       SetHandlerStartupState(StartupState::kFailed);
645       return false;
646     }
647 
648     // In asynchronous mode, we can't report on the overall success or failure
649     // of initialization at this point.
650     return true;
651   } else {
652     return StartHandlerProcess(
653         std::unique_ptr<BackgroundHandlerStartThreadData>(data));
654   }
655 }
656 
SetHandlerIPCPipe(const std::wstring & ipc_pipe)657 bool CrashpadClient::SetHandlerIPCPipe(const std::wstring& ipc_pipe) {
658   DCHECK(ipc_pipe_.empty());
659   DCHECK(!ipc_pipe.empty());
660 
661   ipc_pipe_ = ipc_pipe;
662 
663   DCHECK(!ipc_pipe_.empty());
664   DCHECK_EQ(g_signal_exception, INVALID_HANDLE_VALUE);
665   DCHECK_EQ(g_signal_non_crash_dump, INVALID_HANDLE_VALUE);
666   DCHECK_EQ(g_non_crash_dump_done, INVALID_HANDLE_VALUE);
667   DCHECK(!g_critical_section_with_debug_info.DebugInfo);
668   DCHECK(!g_non_crash_dump_lock);
669 
670   ClientToServerMessage message;
671   memset(&message, 0, sizeof(message));
672   message.type = ClientToServerMessage::kRegister;
673   message.registration.version = RegistrationRequest::kMessageVersion;
674   message.registration.client_process_id = GetCurrentProcessId();
675   message.registration.crash_exception_information =
676       FromPointerCast<WinVMAddress>(&g_crash_exception_information);
677   message.registration.non_crash_exception_information =
678       FromPointerCast<WinVMAddress>(&g_non_crash_exception_information);
679 
680   CommonInProcessInitialization();
681 
682   message.registration.critical_section_address =
683       FromPointerCast<WinVMAddress>(&g_critical_section_with_debug_info);
684 
685   ServerToClientMessage response = {};
686 
687   if (!SendToCrashHandlerServer(ipc_pipe_, message, &response)) {
688     return false;
689   }
690 
691   SetHandlerStartupState(StartupState::kSucceeded);
692 
693   RegisterHandlers();
694 
695   // The server returns these already duplicated to be valid in this process.
696   g_signal_exception =
697       IntToHandle(response.registration.request_crash_dump_event);
698   g_signal_non_crash_dump =
699       IntToHandle(response.registration.request_non_crash_dump_event);
700   g_non_crash_dump_done =
701       IntToHandle(response.registration.non_crash_dump_completed_event);
702 
703   return true;
704 }
705 
GetHandlerIPCPipe() const706 std::wstring CrashpadClient::GetHandlerIPCPipe() const {
707   DCHECK(!ipc_pipe_.empty());
708   return ipc_pipe_;
709 }
710 
WaitForHandlerStart(unsigned int timeout_ms)711 bool CrashpadClient::WaitForHandlerStart(unsigned int timeout_ms) {
712   DCHECK(handler_start_thread_.is_valid());
713   DWORD result = WaitForSingleObject(handler_start_thread_.get(), timeout_ms);
714   if (result == WAIT_TIMEOUT) {
715     LOG(ERROR) << "WaitForSingleObject timed out";
716     return false;
717   } else if (result == WAIT_ABANDONED) {
718     LOG(ERROR) << "WaitForSingleObject abandoned";
719     return false;
720   } else if (result != WAIT_OBJECT_0) {
721     PLOG(ERROR) << "WaitForSingleObject";
722     return false;
723   }
724 
725   DWORD exit_code;
726   if (!GetExitCodeThread(handler_start_thread_.get(), &exit_code)) {
727     PLOG(ERROR) << "GetExitCodeThread";
728     return false;
729   }
730 
731   handler_start_thread_.reset();
732   return exit_code == 0;
733 }
734 
735 // static
DumpWithoutCrash(const CONTEXT & context)736 void CrashpadClient::DumpWithoutCrash(const CONTEXT& context) {
737   if (g_signal_non_crash_dump == INVALID_HANDLE_VALUE ||
738       g_non_crash_dump_done == INVALID_HANDLE_VALUE) {
739     LOG(ERROR) << "not connected";
740     return;
741   }
742 
743   if (BlockUntilHandlerStartedOrFailed() == StartupState::kFailed) {
744     // If we know for certain that the handler has failed to start, then abort
745     // here, as we would otherwise wait indefinitely for the
746     // g_non_crash_dump_done event that would never be signalled.
747     LOG(ERROR) << "crash server failed to launch, no dump captured";
748     return;
749   }
750 
751   // In the non-crashing case, we aren't concerned about avoiding calls into
752   // Win32 APIs, so just use regular locking here in case of multiple threads
753   // calling this function. If a crash occurs while we're in here, the worst
754   // that can happen is that the server captures a partial dump for this path
755   // because another thread’s crash processing finished and the process was
756   // terminated before this thread’s non-crash processing could be completed.
757   base::AutoLock lock(*g_non_crash_dump_lock);
758 
759   // Create a fake EXCEPTION_POINTERS to give the handler something to work
760   // with.
761   EXCEPTION_POINTERS exception_pointers = {};
762 
763   // This is logically const, but EXCEPTION_POINTERS does not declare it as
764   // const, so we have to cast that away from the argument.
765   exception_pointers.ContextRecord = const_cast<CONTEXT*>(&context);
766 
767   // We include a fake exception and use a code of '0x517a7ed' (something like
768   // "simulated") so that it's relatively obvious in windbg that it's not
769   // actually an exception. Most values in
770   // https://msdn.microsoft.com/library/aa363082.aspx have some of the top
771   // nibble set, so we make sure to pick a value that doesn't, so as to be
772   // unlikely to conflict.
773   constexpr uint32_t kSimulatedExceptionCode = 0x517a7ed;
774   EXCEPTION_RECORD record = {};
775   record.ExceptionCode = kSimulatedExceptionCode;
776   record.ExceptionAddress = ProgramCounterFromCONTEXT(&context);
777 
778   exception_pointers.ExceptionRecord = &record;
779 
780   g_non_crash_exception_information.thread_id = GetCurrentThreadId();
781   g_non_crash_exception_information.exception_pointers =
782       FromPointerCast<WinVMAddress>(&exception_pointers);
783 
784   bool set_event_result = !!SetEvent(g_signal_non_crash_dump);
785   PLOG_IF(ERROR, !set_event_result) << "SetEvent";
786 
787   DWORD wfso_result = WaitForSingleObject(g_non_crash_dump_done, INFINITE);
788   PLOG_IF(ERROR, wfso_result != WAIT_OBJECT_0) << "WaitForSingleObject";
789 }
790 
791 // static
DumpAndCrash(EXCEPTION_POINTERS * exception_pointers)792 void CrashpadClient::DumpAndCrash(EXCEPTION_POINTERS* exception_pointers) {
793   if (g_signal_exception == INVALID_HANDLE_VALUE) {
794     LOG(ERROR) << "not connected";
795     SafeTerminateProcess(GetCurrentProcess(),
796                          kTerminationCodeNotConnectedToHandler);
797     return;
798   }
799 
800   // We don't need to check for handler startup here, as
801   // UnhandledExceptionHandler() necessarily does that.
802 
803   UnhandledExceptionHandler(exception_pointers);
804 }
805 
806 // static
DumpAndCrashTargetProcess(HANDLE process,HANDLE blame_thread,DWORD exception_code)807 bool CrashpadClient::DumpAndCrashTargetProcess(HANDLE process,
808                                                HANDLE blame_thread,
809                                                DWORD exception_code) {
810   // Confirm we're on Vista or later.
811   const DWORD version = GetVersion();
812   const DWORD major_version = LOBYTE(LOWORD(version));
813   if (major_version < 6) {
814     LOG(ERROR) << "unavailable before Vista";
815     return false;
816   }
817 
818   // Confirm that our bitness is the same as the process we're crashing.
819   ProcessInfo process_info;
820   if (!process_info.Initialize(process)) {
821     LOG(ERROR) << "ProcessInfo::Initialize";
822     return false;
823   }
824 #if defined(ARCH_CPU_64_BITS)
825   if (!process_info.Is64Bit()) {
826     LOG(ERROR) << "DumpAndCrashTargetProcess currently not supported x64->x86";
827     return false;
828   }
829 #endif  // ARCH_CPU_64_BITS
830 
831   ScopedProcessSuspend suspend(process);
832 
833   // If no thread handle was provided, or the thread has already exited, we pass
834   // 0 to the handler, which indicates no fake exception record to be created.
835   DWORD thread_id = 0;
836   if (blame_thread) {
837     // Now that we've suspended the process, if our thread hasn't exited, we
838     // know we're relatively safe to pass the thread id through.
839     if (WaitForSingleObject(blame_thread, 0) == WAIT_TIMEOUT) {
840       static const auto get_thread_id =
841           GET_FUNCTION_REQUIRED(L"kernel32.dll", ::GetThreadId);
842       thread_id = get_thread_id(blame_thread);
843     }
844   }
845 
846   constexpr size_t kInjectBufferSize = 4 * 1024;
847   WinVMAddress inject_memory =
848       FromPointerCast<WinVMAddress>(VirtualAllocEx(process,
849                                                    nullptr,
850                                                    kInjectBufferSize,
851                                                    MEM_RESERVE | MEM_COMMIT,
852                                                    PAGE_READWRITE));
853   if (!inject_memory) {
854     PLOG(ERROR) << "VirtualAllocEx";
855     return false;
856   }
857 
858   // Because we're the same bitness as our target, we can rely kernel32 being
859   // loaded at the same address in our process as the target, and just look up
860   // its address here.
861   WinVMAddress raise_exception_address =
862       FromPointerCast<WinVMAddress>(&RaiseException);
863 
864   WinVMAddress code_entry_point = 0;
865   std::vector<unsigned char> data_to_write;
866   if (process_info.Is64Bit()) {
867     // Data written is first, the data for the 4th argument (lpArguments) to
868     // RaiseException(). A two element array:
869     //
870     // DWORD64: thread_id
871     // DWORD64: exception_code
872     //
873     // Following that, code which sets the arguments to RaiseException() and
874     // then calls it:
875     //
876     // mov r9, <data_array_address>
877     // mov r8d, 2  ; nNumberOfArguments
878     // mov edx, 1  ; dwExceptionFlags = EXCEPTION_NONCONTINUABLE
879     // mov ecx, 0xcca11ed  ; dwExceptionCode, interpreted specially by the
880     //                     ;                  handler.
881     // jmp <address_of_RaiseException>
882     //
883     // Note that the first three arguments to RaiseException() are DWORDs even
884     // on x64, so only the 4th argument (a pointer) is a full-width register.
885     //
886     // We also don't need to set up a stack or use call, since the only
887     // registers modified are volatile ones, and we can just jmp straight to
888     // RaiseException().
889 
890     // The data array.
891     AddUint64(&data_to_write, thread_id);
892     AddUint64(&data_to_write, exception_code);
893 
894     // The thread entry point.
895     code_entry_point = inject_memory + data_to_write.size();
896 
897     // r9 = pointer to data.
898     data_to_write.push_back(0x49);
899     data_to_write.push_back(0xb9);
900     AddUint64(&data_to_write, inject_memory);
901 
902     // r8d = 2 for nNumberOfArguments.
903     data_to_write.push_back(0x41);
904     data_to_write.push_back(0xb8);
905     AddUint32(&data_to_write, 2);
906 
907     // edx = 1 for dwExceptionFlags.
908     data_to_write.push_back(0xba);
909     AddUint32(&data_to_write, 1);
910 
911     // ecx = kTriggeredExceptionCode for dwExceptionCode.
912     data_to_write.push_back(0xb9);
913     AddUint32(&data_to_write, kTriggeredExceptionCode);
914 
915     // jmp to RaiseException() via rax.
916     data_to_write.push_back(0x48);  // mov rax, imm.
917     data_to_write.push_back(0xb8);
918     AddUint64(&data_to_write, raise_exception_address);
919     data_to_write.push_back(0xff);  // jmp rax.
920     data_to_write.push_back(0xe0);
921   } else {
922     // Data written is first, the data for the 4th argument (lpArguments) to
923     // RaiseException(). A two element array:
924     //
925     // DWORD: thread_id
926     // DWORD: exception_code
927     //
928     // Following that, code which pushes our arguments to RaiseException() and
929     // then calls it:
930     //
931     // push <data_array_address>
932     // push 2  ; nNumberOfArguments
933     // push 1  ; dwExceptionFlags = EXCEPTION_NONCONTINUABLE
934     // push 0xcca11ed  ; dwExceptionCode, interpreted specially by the handler.
935     // call <address_of_RaiseException>
936     // ud2  ; Generate invalid opcode to make sure we still crash if we return
937     //      ; for some reason.
938     //
939     // No need to clean up the stack, as RaiseException() is __stdcall.
940 
941     // The data array.
942     AddUint32(&data_to_write, thread_id);
943     AddUint32(&data_to_write, exception_code);
944 
945     // The thread entry point.
946     code_entry_point = inject_memory + data_to_write.size();
947 
948     // Push data address.
949     data_to_write.push_back(0x68);
950     AddUint32(&data_to_write, static_cast<uint32_t>(inject_memory));
951 
952     // Push 2 for nNumberOfArguments.
953     data_to_write.push_back(0x6a);
954     data_to_write.push_back(2);
955 
956     // Push 1 for dwExceptionCode.
957     data_to_write.push_back(0x6a);
958     data_to_write.push_back(1);
959 
960     // Push dwExceptionFlags.
961     data_to_write.push_back(0x68);
962     AddUint32(&data_to_write, kTriggeredExceptionCode);
963 
964     // Relative call to RaiseException().
965     int64_t relative_address_to_raise_exception =
966         raise_exception_address - (inject_memory + data_to_write.size() + 5);
967     data_to_write.push_back(0xe8);
968     AddUint32(&data_to_write,
969               static_cast<uint32_t>(relative_address_to_raise_exception));
970 
971     // ud2.
972     data_to_write.push_back(0x0f);
973     data_to_write.push_back(0x0b);
974   }
975 
976   DCHECK_LT(data_to_write.size(), kInjectBufferSize);
977 
978   SIZE_T bytes_written;
979   if (!WriteProcessMemory(process,
980                           reinterpret_cast<void*>(inject_memory),
981                           data_to_write.data(),
982                           data_to_write.size(),
983                           &bytes_written)) {
984     PLOG(ERROR) << "WriteProcessMemory";
985     return false;
986   }
987 
988   if (bytes_written != data_to_write.size()) {
989     LOG(ERROR) << "WriteProcessMemory unexpected number of bytes";
990     return false;
991   }
992 
993   if (!FlushInstructionCache(
994           process, reinterpret_cast<void*>(inject_memory), bytes_written)) {
995     PLOG(ERROR) << "FlushInstructionCache";
996     return false;
997   }
998 
999   DWORD old_protect;
1000   if (!VirtualProtectEx(process,
1001                         reinterpret_cast<void*>(inject_memory),
1002                         kInjectBufferSize,
1003                         PAGE_EXECUTE_READ,
1004                         &old_protect)) {
1005     PLOG(ERROR) << "VirtualProtectEx";
1006     return false;
1007   }
1008 
1009   // Cause an exception in the target process by creating a thread which calls
1010   // RaiseException with our arguments above. Note that we cannot get away with
1011   // using DebugBreakProcess() (nothing happens unless a debugger is attached)
1012   // and we cannot get away with CreateRemoteThread() because it doesn't work if
1013   // the target is hung waiting for the loader lock. We use NtCreateThreadEx()
1014   // with the SKIP_THREAD_ATTACH flag, which skips various notifications,
1015   // letting this cause an exception, even when the target is stuck in the
1016   // loader lock.
1017   HANDLE injected_thread;
1018 
1019   // This is what DebugBreakProcess() uses.
1020   constexpr size_t kStackSize = 0x4000;
1021 
1022   NTSTATUS status = NtCreateThreadEx(&injected_thread,
1023                                      STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
1024                                      nullptr,
1025                                      process,
1026                                      reinterpret_cast<void*>(code_entry_point),
1027                                      nullptr,
1028                                      THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH,
1029                                      0,
1030                                      kStackSize,
1031                                      0,
1032                                      nullptr);
1033   if (!NT_SUCCESS(status)) {
1034     NTSTATUS_LOG(ERROR, status) << "NtCreateThreadEx";
1035     return false;
1036   }
1037 
1038   // The injected thread raises an exception and ultimately results in process
1039   // termination. The suspension must be made aware that the process may be
1040   // terminating, otherwise it’ll log an extraneous error.
1041   suspend.TolerateTermination();
1042 
1043   bool result = true;
1044   if (WaitForSingleObject(injected_thread, 60 * 1000) != WAIT_OBJECT_0) {
1045     PLOG(ERROR) << "WaitForSingleObject";
1046     result = false;
1047   }
1048 
1049   status = NtClose(injected_thread);
1050   if (!NT_SUCCESS(status)) {
1051     NTSTATUS_LOG(ERROR, status) << "NtClose";
1052     result = false;
1053   }
1054 
1055   return result;
1056 }
1057 
1058 }  // namespace crashpad
1059