xref: /aosp_15_r20/external/google-breakpad/src/client/linux/handler/exception_handler_unittest.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1 // Copyright 2010 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 //     * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //     * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 //     * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>  // Must come first
31 #endif
32 
33 #include <poll.h>
34 #include <pthread.h>
35 #include <stdint.h>
36 #include <unistd.h>
37 #include <signal.h>
38 #include <sys/mman.h>
39 #include <sys/socket.h>
40 #include <sys/uio.h>
41 #include <sys/wait.h>
42 #if defined(__mips__)
43 #include <sys/cachectl.h>
44 #endif
45 
46 #include <string>
47 
48 #include "breakpad_googletest_includes.h"
49 #include "client/linux/handler/exception_handler.h"
50 #include "client/linux/minidump_writer/minidump_writer.h"
51 #include "common/linux/eintr_wrapper.h"
52 #include "common/linux/ignore_ret.h"
53 #include "common/linux/linux_libc_support.h"
54 #include "common/tests/auto_tempdir.h"
55 #include "common/using_std_string.h"
56 #include "third_party/lss/linux_syscall_support.h"
57 #include "google_breakpad/processor/minidump.h"
58 
59 using namespace google_breakpad;
60 
61 namespace {
62 
63 // Flush the instruction cache for a given memory range.
64 // Only required on ARM and mips.
FlushInstructionCache(const char * memory,uint32_t memory_size)65 void FlushInstructionCache(const char* memory, uint32_t memory_size) {
66 #if defined(__arm__)
67   long begin = reinterpret_cast<long>(memory);
68   long end = begin + static_cast<long>(memory_size);
69 # if defined(__ANDROID__)
70   // Provided by Android's <unistd.h>
71   cacheflush(begin, end, 0);
72 # elif defined(__linux__)
73   // GLibc/ARM doesn't provide a wrapper for it, do a direct syscall.
74 #  ifndef __ARM_NR_cacheflush
75 #  define __ARM_NR_cacheflush 0xf0002
76 #  endif
77   syscall(__ARM_NR_cacheflush, begin, end, 0);
78 # else
79 #   error "Your operating system is not supported yet"
80 # endif
81 #elif defined(__mips__)
82 # if defined(__ANDROID__)
83   // Provided by Android's <unistd.h>
84   long begin = reinterpret_cast<long>(memory);
85   long end = begin + static_cast<long>(memory_size);
86 #if _MIPS_SIM == _ABIO32
87   cacheflush(begin, end, 0);
88 #else
89   syscall(__NR_cacheflush, begin, end, ICACHE);
90 #endif
91 # elif defined(__linux__)
92   // See http://www.linux-mips.org/wiki/Cacheflush_Syscall.
93   cacheflush(const_cast<char*>(memory), memory_size, ICACHE);
94 # else
95 #   error "Your operating system is not supported yet"
96 # endif
97 #endif
98 }
99 
sigchld_handler(int signo)100 void sigchld_handler(int signo) { }
101 
CreateTMPFile(const string & dir,string * path)102 int CreateTMPFile(const string& dir, string* path) {
103   string file = dir + "/exception-handler-unittest.XXXXXX";
104   const char* c_file = file.c_str();
105   // Copy that string, mkstemp needs a C string it can modify.
106   char* c_path = strdup(c_file);
107   const int fd = mkstemp(c_path);
108   if (fd >= 0)
109     *path = c_path;
110   free(c_path);
111   return fd;
112 }
113 
114 class ExceptionHandlerTest : public ::testing::Test {
115  protected:
SetUp()116   void SetUp() {
117     // We need to be able to wait for children, so SIGCHLD cannot be SIG_IGN.
118     struct sigaction sa;
119     memset(&sa, 0, sizeof(sa));
120     sa.sa_handler = sigchld_handler;
121     ASSERT_NE(sigaction(SIGCHLD, &sa, &old_action), -1);
122   }
123 
TearDown()124   void TearDown() {
125     sigaction(SIGCHLD, &old_action, NULL);
126   }
127 
128   struct sigaction old_action;
129 };
130 
131 
WaitForProcessToTerminate(pid_t process_id,int expected_status)132 void WaitForProcessToTerminate(pid_t process_id, int expected_status) {
133   int status;
134   ASSERT_NE(HANDLE_EINTR(waitpid(process_id, &status, 0)), -1);
135   ASSERT_TRUE(WIFSIGNALED(status));
136   ASSERT_EQ(expected_status, WTERMSIG(status));
137 }
138 
139 // Reads the minidump path sent over the pipe |fd| and sets it in |path|.
ReadMinidumpPathFromPipe(int fd,string * path)140 void ReadMinidumpPathFromPipe(int fd, string* path) {
141   struct pollfd pfd;
142   memset(&pfd, 0, sizeof(pfd));
143   pfd.fd = fd;
144   pfd.events = POLLIN | POLLERR;
145 
146   const int r = HANDLE_EINTR(poll(&pfd, 1, 0));
147   ASSERT_EQ(1, r);
148   ASSERT_TRUE(pfd.revents & POLLIN);
149 
150   int32_t len;
151   ASSERT_EQ(static_cast<ssize_t>(sizeof(len)), read(fd, &len, sizeof(len)));
152   ASSERT_LT(len, 2048);
153   char* filename = static_cast<char*>(malloc(len + 1));
154   ASSERT_EQ(len, read(fd, filename, len));
155   filename[len] = 0;
156   close(fd);
157   *path = filename;
158   free(filename);
159 }
160 
161 }  // namespace
162 
TEST(ExceptionHandlerTest,SimpleWithPath)163 TEST(ExceptionHandlerTest, SimpleWithPath) {
164   AutoTempDir temp_dir;
165   ExceptionHandler handler(
166       MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
167   EXPECT_EQ(temp_dir.path(), handler.minidump_descriptor().directory());
168   string temp_subdir = temp_dir.path() + "/subdir";
169   handler.set_minidump_descriptor(MinidumpDescriptor(temp_subdir));
170   EXPECT_EQ(temp_subdir, handler.minidump_descriptor().directory());
171 }
172 
TEST(ExceptionHandlerTest,SimpleWithFD)173 TEST(ExceptionHandlerTest, SimpleWithFD) {
174   AutoTempDir temp_dir;
175   string path;
176   const int fd = CreateTMPFile(temp_dir.path(), &path);
177   ExceptionHandler handler(MinidumpDescriptor(fd), NULL, NULL, NULL, true, -1);
178   close(fd);
179 }
180 
DoneCallback(const MinidumpDescriptor & descriptor,void * context,bool succeeded)181 static bool DoneCallback(const MinidumpDescriptor& descriptor,
182                          void* context,
183                          bool succeeded) {
184   if (!succeeded)
185     return false;
186 
187   if (!descriptor.IsFD()) {
188     int fd = reinterpret_cast<intptr_t>(context);
189     uint32_t len = 0;
190     len = my_strlen(descriptor.path());
191     IGNORE_RET(HANDLE_EINTR(sys_write(fd, &len, sizeof(len))));
192     IGNORE_RET(HANDLE_EINTR(sys_write(fd, descriptor.path(), len)));
193   }
194   return true;
195 }
196 
197 #ifndef ADDRESS_SANITIZER
198 
199 // This is a replacement for "*reinterpret_cast<volatile int*>(NULL) = 0;"
200 // It is needed because GCC is allowed to assume that the program will
201 // not execute any undefined behavior (UB) operation. Further, when GCC
202 // observes that UB statement is reached, it can assume that all statements
203 // leading to the UB one are never executed either, and can completely
204 // optimize them out. In the case of ExceptionHandlerTest::ExternalDumper,
205 // GCC-4.9 optimized out the entire set up of ExceptionHandler, causing
206 // test failure.
207 volatile int* p_null;  // external linkage, so GCC can't tell that it
208                        // remains NULL. Volatile just for a good measure.
DoNullPointerDereference()209 static void DoNullPointerDereference() {
210   *p_null = 1;
211 }
212 
ChildCrash(bool use_fd)213 void ChildCrash(bool use_fd) {
214   AutoTempDir temp_dir;
215   int fds[2] = {0};
216   int minidump_fd = -1;
217   string minidump_path;
218   if (use_fd) {
219     minidump_fd = CreateTMPFile(temp_dir.path(), &minidump_path);
220   } else {
221     ASSERT_NE(pipe(fds), -1);
222   }
223 
224   const pid_t child = fork();
225   if (child == 0) {
226     {
227       google_breakpad::scoped_ptr<ExceptionHandler> handler;
228       if (use_fd) {
229         handler.reset(new ExceptionHandler(MinidumpDescriptor(minidump_fd),
230                                            NULL, NULL, NULL, true, -1));
231       } else {
232         close(fds[0]);  // Close the reading end.
233         void* fd_param = reinterpret_cast<void*>(fds[1]);
234         handler.reset(new ExceptionHandler(MinidumpDescriptor(temp_dir.path()),
235                                            NULL, DoneCallback, fd_param,
236                                            true, -1));
237       }
238       // Crash with the exception handler in scope.
239       DoNullPointerDereference();
240     }
241   }
242   if (!use_fd)
243     close(fds[1]);  // Close the writting end.
244 
245   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
246 
247   if (!use_fd)
248     ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
249 
250   struct stat st;
251   ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
252   ASSERT_GT(st.st_size, 0);
253   unlink(minidump_path.c_str());
254 }
255 
TEST(ExceptionHandlerTest,ChildCrashWithPath)256 TEST(ExceptionHandlerTest, ChildCrashWithPath) {
257   ASSERT_NO_FATAL_FAILURE(ChildCrash(false));
258 }
259 
TEST(ExceptionHandlerTest,ChildCrashWithFD)260 TEST(ExceptionHandlerTest, ChildCrashWithFD) {
261   ASSERT_NO_FATAL_FAILURE(ChildCrash(true));
262 }
263 
264 #if !defined(__ANDROID_API__) || __ANDROID_API__ >= __ANDROID_API_N__
SleepFunction(void * unused)265 static void* SleepFunction(void* unused) {
266   while (true) usleep(1000000);
267   return NULL;
268 }
269 
CrashFunction(void * b_ptr)270 static void* CrashFunction(void* b_ptr) {
271   pthread_barrier_t* b = reinterpret_cast<pthread_barrier_t*>(b_ptr);
272   pthread_barrier_wait(b);
273   DoNullPointerDereference();
274   return NULL;
275 }
276 
277 // Tests that concurrent crashes do not enter a loop by alternately triggering
278 // the signal handler.
TEST(ExceptionHandlerTest,ParallelChildCrashesDontHang)279 TEST(ExceptionHandlerTest, ParallelChildCrashesDontHang) {
280   AutoTempDir temp_dir;
281   const pid_t child = fork();
282   if (child == 0) {
283     google_breakpad::scoped_ptr<ExceptionHandler> handler(
284       new ExceptionHandler(MinidumpDescriptor(temp_dir.path()), NULL, NULL,
285                             NULL, true, -1));
286 
287     // We start a number of threads to make sure handling the signal takes
288     // enough time for the second thread to enter the signal handler.
289     int num_sleep_threads = 100;
290     google_breakpad::scoped_array<pthread_t> sleep_threads(
291         new pthread_t[num_sleep_threads]);
292     for (int i = 0; i < num_sleep_threads; ++i) {
293       ASSERT_EQ(0, pthread_create(&sleep_threads[i], NULL, SleepFunction,
294                                   NULL));
295     }
296 
297     int num_crash_threads = 2;
298     google_breakpad::scoped_array<pthread_t> crash_threads(
299         new pthread_t[num_crash_threads]);
300     // Barrier to synchronize crashing both threads at the same time.
301     pthread_barrier_t b;
302     ASSERT_EQ(0, pthread_barrier_init(&b, NULL, num_crash_threads + 1));
303     for (int i = 0; i < num_crash_threads; ++i) {
304       ASSERT_EQ(0, pthread_create(&crash_threads[i], NULL, CrashFunction, &b));
305     }
306     pthread_barrier_wait(&b);
307     for (int i = 0; i < num_crash_threads; ++i) {
308       ASSERT_EQ(0, pthread_join(crash_threads[i], NULL));
309     }
310   }
311 
312   // Poll the child to see if it crashed.
313   int status, wp_pid;
314   for (int i = 0; i < 100; i++) {
315     wp_pid = HANDLE_EINTR(waitpid(child, &status, WNOHANG));
316     ASSERT_NE(-1, wp_pid);
317     if (wp_pid > 0) {
318       ASSERT_TRUE(WIFSIGNALED(status));
319       // If the child process terminated by itself,
320       // it will have returned SIGSEGV.
321       ASSERT_EQ(SIGSEGV, WTERMSIG(status));
322       return;
323     } else {
324       usleep(100000);
325     }
326   }
327 
328   // Kill the child if it is still running.
329   kill(child, SIGKILL);
330 
331   // If the child process terminated by itself, it will have returned SIGSEGV.
332   // If however it got stuck in a loop, it will have been killed by the
333   // SIGKILL.
334   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
335 }
336 #endif  // !defined(__ANDROID_API__) || __ANDROID_API__ >= __ANDROID_API_N__
337 
DoneCallbackReturnFalse(const MinidumpDescriptor & descriptor,void * context,bool succeeded)338 static bool DoneCallbackReturnFalse(const MinidumpDescriptor& descriptor,
339                                     void* context,
340                                     bool succeeded) {
341   return false;
342 }
343 
DoneCallbackReturnTrue(const MinidumpDescriptor & descriptor,void * context,bool succeeded)344 static bool DoneCallbackReturnTrue(const MinidumpDescriptor& descriptor,
345                                    void* context,
346                                    bool succeeded) {
347   return true;
348 }
349 
DoneCallbackRaiseSIGKILL(const MinidumpDescriptor & descriptor,void * context,bool succeeded)350 static bool DoneCallbackRaiseSIGKILL(const MinidumpDescriptor& descriptor,
351                                      void* context,
352                                      bool succeeded) {
353   raise(SIGKILL);
354   return true;
355 }
356 
FilterCallbackReturnFalse(void * context)357 static bool FilterCallbackReturnFalse(void* context) {
358   return false;
359 }
360 
FilterCallbackReturnTrue(void * context)361 static bool FilterCallbackReturnTrue(void* context) {
362   return true;
363 }
364 
365 // SIGKILL cannot be blocked and a handler cannot be installed for it. In the
366 // following tests, if the child dies with signal SIGKILL, then the signal was
367 // redelivered to this handler. If the child dies with SIGSEGV then it wasn't.
RaiseSIGKILL(int sig)368 static void RaiseSIGKILL(int sig) {
369   raise(SIGKILL);
370 }
371 
InstallRaiseSIGKILL()372 static bool InstallRaiseSIGKILL() {
373   struct sigaction sa;
374   memset(&sa, 0, sizeof(sa));
375   sa.sa_handler = RaiseSIGKILL;
376   return sigaction(SIGSEGV, &sa, NULL) != -1;
377 }
378 
CrashWithCallbacks(ExceptionHandler::FilterCallback filter,ExceptionHandler::MinidumpCallback done,string path)379 static void CrashWithCallbacks(ExceptionHandler::FilterCallback filter,
380                                ExceptionHandler::MinidumpCallback done,
381                                string path) {
382   ExceptionHandler handler(
383       MinidumpDescriptor(path), filter, done, NULL, true, -1);
384   // Crash with the exception handler in scope.
385   DoNullPointerDereference();
386 }
387 
TEST(ExceptionHandlerTest,RedeliveryOnFilterCallbackFalse)388 TEST(ExceptionHandlerTest, RedeliveryOnFilterCallbackFalse) {
389   AutoTempDir temp_dir;
390 
391   const pid_t child = fork();
392   if (child == 0) {
393     ASSERT_TRUE(InstallRaiseSIGKILL());
394     CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path());
395   }
396 
397   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
398 }
399 
TEST(ExceptionHandlerTest,RedeliveryOnDoneCallbackFalse)400 TEST(ExceptionHandlerTest, RedeliveryOnDoneCallbackFalse) {
401   AutoTempDir temp_dir;
402 
403   const pid_t child = fork();
404   if (child == 0) {
405     ASSERT_TRUE(InstallRaiseSIGKILL());
406     CrashWithCallbacks(NULL, DoneCallbackReturnFalse, temp_dir.path());
407   }
408 
409   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
410 }
411 
TEST(ExceptionHandlerTest,NoRedeliveryOnDoneCallbackTrue)412 TEST(ExceptionHandlerTest, NoRedeliveryOnDoneCallbackTrue) {
413   AutoTempDir temp_dir;
414 
415   const pid_t child = fork();
416   if (child == 0) {
417     ASSERT_TRUE(InstallRaiseSIGKILL());
418     CrashWithCallbacks(NULL, DoneCallbackReturnTrue, temp_dir.path());
419   }
420 
421   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
422 }
423 
TEST(ExceptionHandlerTest,NoRedeliveryOnFilterCallbackTrue)424 TEST(ExceptionHandlerTest, NoRedeliveryOnFilterCallbackTrue) {
425   AutoTempDir temp_dir;
426 
427   const pid_t child = fork();
428   if (child == 0) {
429     ASSERT_TRUE(InstallRaiseSIGKILL());
430     CrashWithCallbacks(FilterCallbackReturnTrue, NULL, temp_dir.path());
431   }
432 
433   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
434 }
435 
TEST(ExceptionHandlerTest,RedeliveryToDefaultHandler)436 TEST(ExceptionHandlerTest, RedeliveryToDefaultHandler) {
437   AutoTempDir temp_dir;
438 
439   const pid_t child = fork();
440   if (child == 0) {
441     // Custom signal handlers, which may have been installed by a test launcher,
442     // are undesirable in this child.
443     signal(SIGSEGV, SIG_DFL);
444 
445     CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path());
446   }
447 
448   // As RaiseSIGKILL wasn't installed, the redelivery should just kill the child
449   // with SIGSEGV.
450   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
451 }
452 
453 // Check that saving and restoring the signal handler with 'signal'
454 // instead of 'sigaction' doesn't make the Breakpad signal handler
455 // crash. See comments in ExceptionHandler::SignalHandler for full
456 // details.
TEST(ExceptionHandlerTest,RedeliveryOnBadSignalHandlerFlag)457 TEST(ExceptionHandlerTest, RedeliveryOnBadSignalHandlerFlag) {
458   AutoTempDir temp_dir;
459   const pid_t child = fork();
460   if (child == 0) {
461     // Install the RaiseSIGKILL handler for SIGSEGV.
462     ASSERT_TRUE(InstallRaiseSIGKILL());
463 
464     // Create a new exception handler, this installs a new SIGSEGV
465     // handler, after saving the old one.
466     ExceptionHandler handler(
467         MinidumpDescriptor(temp_dir.path()), NULL,
468         DoneCallbackReturnFalse, NULL, true, -1);
469 
470     // Install the default SIGSEGV handler, saving the current one.
471     // Then re-install the current one with 'signal', this loses the
472     // SA_SIGINFO flag associated with the Breakpad handler.
473     sighandler_t old_handler = signal(SIGSEGV, SIG_DFL);
474     ASSERT_NE(reinterpret_cast<void*>(old_handler),
475               reinterpret_cast<void*>(SIG_ERR));
476     ASSERT_NE(reinterpret_cast<void*>(signal(SIGSEGV, old_handler)),
477               reinterpret_cast<void*>(SIG_ERR));
478 
479     // Crash with the exception handler in scope.
480     DoNullPointerDereference();
481   }
482   // SIGKILL means Breakpad's signal handler didn't crash.
483   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
484 }
485 
TEST(ExceptionHandlerTest,StackedHandlersDeliveredToTop)486 TEST(ExceptionHandlerTest, StackedHandlersDeliveredToTop) {
487   AutoTempDir temp_dir;
488 
489   const pid_t child = fork();
490   if (child == 0) {
491     ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
492                             NULL,
493                             NULL,
494                             NULL,
495                             true,
496                             -1);
497     CrashWithCallbacks(NULL, DoneCallbackRaiseSIGKILL, temp_dir.path());
498   }
499   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
500 }
501 
TEST(ExceptionHandlerTest,StackedHandlersNotDeliveredToBottom)502 TEST(ExceptionHandlerTest, StackedHandlersNotDeliveredToBottom) {
503   AutoTempDir temp_dir;
504 
505   const pid_t child = fork();
506   if (child == 0) {
507     ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
508                             NULL,
509                             DoneCallbackRaiseSIGKILL,
510                             NULL,
511                             true,
512                             -1);
513     CrashWithCallbacks(NULL, NULL, temp_dir.path());
514   }
515   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
516 }
517 
TEST(ExceptionHandlerTest,StackedHandlersFilteredToBottom)518 TEST(ExceptionHandlerTest, StackedHandlersFilteredToBottom) {
519   AutoTempDir temp_dir;
520 
521   const pid_t child = fork();
522   if (child == 0) {
523     ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
524                             NULL,
525                             DoneCallbackRaiseSIGKILL,
526                             NULL,
527                             true,
528                             -1);
529     CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path());
530   }
531   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
532 }
533 
TEST(ExceptionHandlerTest,StackedHandlersUnhandledToBottom)534 TEST(ExceptionHandlerTest, StackedHandlersUnhandledToBottom) {
535   AutoTempDir temp_dir;
536 
537   const pid_t child = fork();
538   if (child == 0) {
539     ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()),
540                             NULL,
541                             DoneCallbackRaiseSIGKILL,
542                             NULL,
543                             true,
544                             -1);
545     CrashWithCallbacks(NULL, DoneCallbackReturnFalse, temp_dir.path());
546   }
547   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
548 }
549 
550 namespace {
551 const int kSimpleFirstChanceReturnStatus = 42;
SimpleFirstChanceHandler(int,siginfo_t *,void *)552 bool SimpleFirstChanceHandler(int, siginfo_t*, void*) {
553   _exit(kSimpleFirstChanceReturnStatus);
554 }
555 }
556 
TEST(ExceptionHandlerTest,FirstChanceHandlerRuns)557 TEST(ExceptionHandlerTest, FirstChanceHandlerRuns) {
558   AutoTempDir temp_dir;
559 
560   const pid_t child = fork();
561   if (child == 0) {
562     ExceptionHandler handler(
563         MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
564     google_breakpad::SetFirstChanceExceptionHandler(SimpleFirstChanceHandler);
565     DoNullPointerDereference();
566   }
567   int status;
568   ASSERT_NE(HANDLE_EINTR(waitpid(child, &status, 0)), -1);
569   ASSERT_TRUE(WIFEXITED(status));
570   ASSERT_EQ(kSimpleFirstChanceReturnStatus, WEXITSTATUS(status));
571 }
572 
573 #endif  // !ADDRESS_SANITIZER
574 
575 const unsigned char kIllegalInstruction[] = {
576 #if defined(__mips__)
577   // mfc2 zero,Impl - usually illegal in userspace.
578   0x48, 0x00, 0x00, 0x48
579 #else
580   // This crashes with SIGILL on x86/x86-64/arm.
581   0xff, 0xff, 0xff, 0xff
582 #endif
583 };
584 
585 // Test that memory around the instruction pointer is written
586 // to the dump as a MinidumpMemoryRegion.
TEST(ExceptionHandlerTest,InstructionPointerMemory)587 TEST(ExceptionHandlerTest, InstructionPointerMemory) {
588   AutoTempDir temp_dir;
589   int fds[2];
590   ASSERT_NE(pipe(fds), -1);
591 
592   // These are defined here so the parent can use them to check the
593   // data from the minidump afterwards.
594   const uint32_t kMemorySize = 256;  // bytes
595   const int kOffset = kMemorySize / 2;
596 
597   const pid_t child = fork();
598   if (child == 0) {
599     close(fds[0]);
600     ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
601                              DoneCallback, reinterpret_cast<void*>(fds[1]),
602                              true, -1);
603     // Get some executable memory.
604     char* memory =
605       reinterpret_cast<char*>(mmap(NULL,
606                                    kMemorySize,
607                                    PROT_READ | PROT_WRITE | PROT_EXEC,
608                                    MAP_PRIVATE | MAP_ANON,
609                                    -1,
610                                    0));
611     if (!memory)
612       exit(0);
613 
614     // Write some instructions that will crash. Put them in the middle
615     // of the block of memory, because the minidump should contain 128
616     // bytes on either side of the instruction pointer.
617     memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
618     FlushInstructionCache(memory, kMemorySize);
619 
620     // Now execute the instructions, which should crash.
621     typedef void (*void_function)(void);
622     void_function memory_function =
623         reinterpret_cast<void_function>(memory + kOffset);
624     memory_function();
625   }
626   close(fds[1]);
627 
628   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGILL));
629 
630   string minidump_path;
631   ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
632 
633   struct stat st;
634   ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
635   ASSERT_GT(st.st_size, 0);
636 
637   // Read the minidump. Locate the exception record and the
638   // memory list, and then ensure that there is a memory region
639   // in the memory list that covers the instruction pointer from
640   // the exception record.
641   Minidump minidump(minidump_path);
642   ASSERT_TRUE(minidump.Read());
643 
644   MinidumpException* exception = minidump.GetException();
645   MinidumpMemoryList* memory_list = minidump.GetMemoryList();
646   ASSERT_TRUE(exception);
647   ASSERT_TRUE(memory_list);
648   ASSERT_LT(0U, memory_list->region_count());
649 
650   MinidumpContext* context = exception->GetContext();
651   ASSERT_TRUE(context);
652 
653   uint64_t instruction_pointer;
654   ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
655 
656   MinidumpMemoryRegion* region =
657       memory_list->GetMemoryRegionForAddress(instruction_pointer);
658   ASSERT_TRUE(region);
659 
660   EXPECT_EQ(kMemorySize, region->GetSize());
661   const uint8_t* bytes = region->GetMemory();
662   ASSERT_TRUE(bytes);
663 
664   uint8_t prefix_bytes[kOffset];
665   uint8_t suffix_bytes[kMemorySize - kOffset - sizeof(kIllegalInstruction)];
666   memset(prefix_bytes, 0, sizeof(prefix_bytes));
667   memset(suffix_bytes, 0, sizeof(suffix_bytes));
668   EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
669   EXPECT_TRUE(memcmp(bytes + kOffset, kIllegalInstruction,
670                      sizeof(kIllegalInstruction)) == 0);
671   EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(kIllegalInstruction),
672                      suffix_bytes, sizeof(suffix_bytes)) == 0);
673 
674   unlink(minidump_path.c_str());
675 }
676 
677 // Test that the memory region around the instruction pointer is
678 // bounded correctly on the low end.
TEST(ExceptionHandlerTest,InstructionPointerMemoryMinBound)679 TEST(ExceptionHandlerTest, InstructionPointerMemoryMinBound) {
680   AutoTempDir temp_dir;
681   int fds[2];
682   ASSERT_NE(pipe(fds), -1);
683 
684   // These are defined here so the parent can use them to check the
685   // data from the minidump afterwards.
686   const uint32_t kMemorySize = 256;  // bytes
687   const int kOffset = 0;
688 
689   const pid_t child = fork();
690   if (child == 0) {
691     close(fds[0]);
692     ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
693                              DoneCallback, reinterpret_cast<void*>(fds[1]),
694                              true, -1);
695     // Get some executable memory.
696     char* memory =
697         reinterpret_cast<char*>(mmap(NULL,
698                                      kMemorySize,
699                                      PROT_READ | PROT_WRITE | PROT_EXEC,
700                                      MAP_PRIVATE | MAP_ANON,
701                                      -1,
702                                      0));
703     if (!memory)
704       exit(0);
705 
706     // Write some instructions that will crash. Put them in the middle
707     // of the block of memory, because the minidump should contain 128
708     // bytes on either side of the instruction pointer.
709     memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
710     FlushInstructionCache(memory, kMemorySize);
711 
712     // Now execute the instructions, which should crash.
713     typedef void (*void_function)(void);
714     void_function memory_function =
715         reinterpret_cast<void_function>(memory + kOffset);
716     memory_function();
717   }
718   close(fds[1]);
719 
720   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGILL));
721 
722   string minidump_path;
723   ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
724 
725   struct stat st;
726   ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
727   ASSERT_GT(st.st_size, 0);
728 
729   // Read the minidump. Locate the exception record and the
730   // memory list, and then ensure that there is a memory region
731   // in the memory list that covers the instruction pointer from
732   // the exception record.
733   Minidump minidump(minidump_path);
734   ASSERT_TRUE(minidump.Read());
735 
736   MinidumpException* exception = minidump.GetException();
737   MinidumpMemoryList* memory_list = minidump.GetMemoryList();
738   ASSERT_TRUE(exception);
739   ASSERT_TRUE(memory_list);
740   ASSERT_LT(0U, memory_list->region_count());
741 
742   MinidumpContext* context = exception->GetContext();
743   ASSERT_TRUE(context);
744 
745   uint64_t instruction_pointer;
746   ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
747 
748   MinidumpMemoryRegion* region =
749       memory_list->GetMemoryRegionForAddress(instruction_pointer);
750   ASSERT_TRUE(region);
751 
752   EXPECT_EQ(kMemorySize / 2, region->GetSize());
753   const uint8_t* bytes = region->GetMemory();
754   ASSERT_TRUE(bytes);
755 
756   uint8_t suffix_bytes[kMemorySize / 2 - sizeof(kIllegalInstruction)];
757   memset(suffix_bytes, 0, sizeof(suffix_bytes));
758   EXPECT_TRUE(memcmp(bytes + kOffset, kIllegalInstruction,
759                      sizeof(kIllegalInstruction)) == 0);
760   EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(kIllegalInstruction),
761                      suffix_bytes, sizeof(suffix_bytes)) == 0);
762   unlink(minidump_path.c_str());
763 }
764 
765 // Test that the memory region around the instruction pointer is
766 // bounded correctly on the high end.
TEST(ExceptionHandlerTest,InstructionPointerMemoryMaxBound)767 TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
768   AutoTempDir temp_dir;
769   int fds[2];
770   ASSERT_NE(pipe(fds), -1);
771 
772   // These are defined here so the parent can use them to check the
773   // data from the minidump afterwards.
774   // Use 4k here because the OS will hand out a single page even
775   // if a smaller size is requested, and this test wants to
776   // test the upper bound of the memory range.
777   const uint32_t kMemorySize = 4096;  // bytes
778   const int kOffset = kMemorySize - sizeof(kIllegalInstruction);
779 
780   const pid_t child = fork();
781   if (child == 0) {
782     close(fds[0]);
783     ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
784                              DoneCallback, reinterpret_cast<void*>(fds[1]),
785                              true, -1);
786     // Get some executable memory.
787     char* memory =
788         reinterpret_cast<char*>(mmap(NULL,
789                                      kMemorySize,
790                                      PROT_READ | PROT_WRITE | PROT_EXEC,
791                                      MAP_PRIVATE | MAP_ANON,
792                                      -1,
793                                      0));
794     if (!memory)
795       exit(0);
796 
797     // Write some instructions that will crash. Put them in the middle
798     // of the block of memory, because the minidump should contain 128
799     // bytes on either side of the instruction pointer.
800     memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
801     FlushInstructionCache(memory, kMemorySize);
802 
803     // Now execute the instructions, which should crash.
804     typedef void (*void_function)(void);
805     void_function memory_function =
806         reinterpret_cast<void_function>(memory + kOffset);
807     memory_function();
808   }
809   close(fds[1]);
810 
811   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGILL));
812 
813   string minidump_path;
814   ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
815 
816   struct stat st;
817   ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
818   ASSERT_GT(st.st_size, 0);
819 
820   // Read the minidump. Locate the exception record and the memory list, and
821   // then ensure that there is a memory region in the memory list that covers
822   // the instruction pointer from the exception record.
823   Minidump minidump(minidump_path);
824   ASSERT_TRUE(minidump.Read());
825 
826   MinidumpException* exception = minidump.GetException();
827   MinidumpMemoryList* memory_list = minidump.GetMemoryList();
828   ASSERT_TRUE(exception);
829   ASSERT_TRUE(memory_list);
830   ASSERT_LT(0U, memory_list->region_count());
831 
832   MinidumpContext* context = exception->GetContext();
833   ASSERT_TRUE(context);
834 
835   uint64_t instruction_pointer;
836   ASSERT_TRUE(context->GetInstructionPointer(&instruction_pointer));
837 
838   MinidumpMemoryRegion* region =
839       memory_list->GetMemoryRegionForAddress(instruction_pointer);
840   ASSERT_TRUE(region);
841 
842   const size_t kPrefixSize = 128;  // bytes
843   EXPECT_EQ(kPrefixSize + sizeof(kIllegalInstruction), region->GetSize());
844   const uint8_t* bytes = region->GetMemory();
845   ASSERT_TRUE(bytes);
846 
847   uint8_t prefix_bytes[kPrefixSize];
848   memset(prefix_bytes, 0, sizeof(prefix_bytes));
849   EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
850   EXPECT_TRUE(memcmp(bytes + kPrefixSize,
851                      kIllegalInstruction, sizeof(kIllegalInstruction)) == 0);
852 
853   unlink(minidump_path.c_str());
854 }
855 
856 #ifndef ADDRESS_SANITIZER
857 
858 // Ensure that an extra memory block doesn't get added when the instruction
859 // pointer is not in mapped memory.
TEST(ExceptionHandlerTest,InstructionPointerMemoryNullPointer)860 TEST(ExceptionHandlerTest, InstructionPointerMemoryNullPointer) {
861   AutoTempDir temp_dir;
862   int fds[2];
863   ASSERT_NE(pipe(fds), -1);
864 
865   const pid_t child = fork();
866   if (child == 0) {
867     close(fds[0]);
868     ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL,
869                              DoneCallback, reinterpret_cast<void*>(fds[1]),
870                              true, -1);
871     // Try calling a NULL pointer.
872     typedef void (*void_function)(void);
873     // Volatile markings are needed to keep Clang from generating invalid
874     // opcodes.  See http://crbug.com/498354 for details.
875     volatile void_function memory_function =
876       reinterpret_cast<void_function>(NULL);
877     memory_function();
878     // not reached
879     exit(1);
880   }
881   close(fds[1]);
882 
883   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
884 
885   string minidump_path;
886   ASSERT_NO_FATAL_FAILURE(ReadMinidumpPathFromPipe(fds[0], &minidump_path));
887 
888   struct stat st;
889   ASSERT_EQ(0, stat(minidump_path.c_str(), &st));
890   ASSERT_GT(st.st_size, 0);
891 
892   // Read the minidump. Locate the exception record and the
893   // memory list, and then ensure that there is no memory region
894   // in the memory list that covers the instruction pointer from
895   // the exception record.
896   Minidump minidump(minidump_path);
897   ASSERT_TRUE(minidump.Read());
898 
899   MinidumpException* exception = minidump.GetException();
900   ASSERT_TRUE(exception);
901 
902   MinidumpContext* exception_context = exception->GetContext();
903   ASSERT_TRUE(exception_context);
904 
905   uint64_t instruction_pointer;
906   ASSERT_TRUE(exception_context->GetInstructionPointer(&instruction_pointer));
907   EXPECT_EQ(instruction_pointer, 0u);
908 
909   MinidumpMemoryList* memory_list = minidump.GetMemoryList();
910   ASSERT_TRUE(memory_list);
911 
912   unsigned int region_count = memory_list->region_count();
913   ASSERT_GE(region_count, 1u);
914 
915   for (unsigned int region_index = 0;
916        region_index < region_count;
917        ++region_index) {
918     MinidumpMemoryRegion* region =
919         memory_list->GetMemoryRegionAtIndex(region_index);
920     uint64_t region_base = region->GetBase();
921     EXPECT_FALSE(instruction_pointer >= region_base &&
922                  instruction_pointer < region_base + region->GetSize());
923   }
924 
925   unlink(minidump_path.c_str());
926 }
927 
928 #endif  // !ADDRESS_SANITIZER
929 
930 // Test that anonymous memory maps can be annotated with names and IDs.
TEST(ExceptionHandlerTest,ModuleInfo)931 TEST(ExceptionHandlerTest, ModuleInfo) {
932   // These are defined here so the parent can use them to check the
933   // data from the minidump afterwards.
934   const uint32_t kMemorySize = sysconf(_SC_PAGESIZE);
935   const char* kMemoryName = "a fake module";
936   const uint8_t kModuleGUID[sizeof(MDGUID)] = {
937     0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
938     0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
939   };
940   const string module_identifier = "33221100554477668899AABBCCDDEEFF0";
941 
942   // Get some memory.
943   char* memory =
944       reinterpret_cast<char*>(mmap(NULL,
945                                    kMemorySize,
946                                    PROT_READ | PROT_WRITE,
947                                    MAP_PRIVATE | MAP_ANON,
948                                    -1,
949                                    0));
950   const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
951   ASSERT_TRUE(memory);
952 
953   AutoTempDir temp_dir;
954   ExceptionHandler handler(
955       MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
956 
957   // Add info about the anonymous memory mapping.
958   handler.AddMappingInfo(kMemoryName,
959                          kModuleGUID,
960                          kMemoryAddress,
961                          kMemorySize,
962                          0);
963   ASSERT_TRUE(handler.WriteMinidump());
964 
965   const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor();
966   // Read the minidump. Load the module list, and ensure that the mmap'ed
967   // |memory| is listed with the given module name and debug ID.
968   Minidump minidump(minidump_desc.path());
969   ASSERT_TRUE(minidump.Read());
970 
971   MinidumpModuleList* module_list = minidump.GetModuleList();
972   ASSERT_TRUE(module_list);
973   const MinidumpModule* module =
974       module_list->GetModuleForAddress(kMemoryAddress);
975   ASSERT_TRUE(module);
976 
977   EXPECT_EQ(kMemoryAddress, module->base_address());
978   EXPECT_EQ(kMemorySize, module->size());
979   EXPECT_EQ(kMemoryName, module->code_file());
980   EXPECT_EQ(module_identifier, module->debug_identifier());
981 
982   unlink(minidump_desc.path());
983 }
984 
985 #ifndef ADDRESS_SANITIZER
986 
987 static const unsigned kControlMsgSize =
988     CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred));
989 
990 static bool
CrashHandler(const void * crash_context,size_t crash_context_size,void * context)991 CrashHandler(const void* crash_context, size_t crash_context_size,
992              void* context) {
993   const int fd = (intptr_t) context;
994   int fds[2];
995   if (pipe(fds) == -1) {
996     // There doesn't seem to be any way to reliably handle
997     // this failure without the parent process hanging
998     // At least make sure that this process doesn't access
999     // unexpected file descriptors
1000     fds[0] = -1;
1001     fds[1] = -1;
1002   }
1003   struct kernel_msghdr msg = {0};
1004   struct kernel_iovec iov;
1005   iov.iov_base = const_cast<void*>(crash_context);
1006   iov.iov_len = crash_context_size;
1007   msg.msg_iov = &iov;
1008   msg.msg_iovlen = 1;
1009   char cmsg[kControlMsgSize];
1010   memset(cmsg, 0, kControlMsgSize);
1011   msg.msg_control = cmsg;
1012   msg.msg_controllen = sizeof(cmsg);
1013 
1014   struct cmsghdr* hdr = CMSG_FIRSTHDR(&msg);
1015   hdr->cmsg_level = SOL_SOCKET;
1016   hdr->cmsg_type = SCM_RIGHTS;
1017   hdr->cmsg_len = CMSG_LEN(sizeof(int));
1018   *((int*) CMSG_DATA(hdr)) = fds[1];
1019   hdr = CMSG_NXTHDR((struct msghdr*) &msg, hdr);
1020   hdr->cmsg_level = SOL_SOCKET;
1021   hdr->cmsg_type = SCM_CREDENTIALS;
1022   hdr->cmsg_len = CMSG_LEN(sizeof(struct ucred));
1023   struct ucred* cred = reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
1024   cred->uid = getuid();
1025   cred->gid = getgid();
1026   cred->pid = getpid();
1027 
1028   ssize_t ret = HANDLE_EINTR(sys_sendmsg(fd, &msg, 0));
1029   sys_close(fds[1]);
1030   if (ret <= 0)
1031     return false;
1032 
1033   char b;
1034   IGNORE_RET(HANDLE_EINTR(sys_read(fds[0], &b, 1)));
1035 
1036   return true;
1037 }
1038 
TEST(ExceptionHandlerTest,ExternalDumper)1039 TEST(ExceptionHandlerTest, ExternalDumper) {
1040   int fds[2];
1041   ASSERT_NE(socketpair(AF_UNIX, SOCK_DGRAM, 0, fds), -1);
1042   static const int on = 1;
1043   setsockopt(fds[0], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
1044   setsockopt(fds[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
1045 
1046   const pid_t child = fork();
1047   if (child == 0) {
1048     close(fds[0]);
1049     ExceptionHandler handler(MinidumpDescriptor("/tmp1"), NULL, NULL,
1050                              reinterpret_cast<void*>(fds[1]), true, -1);
1051     handler.set_crash_handler(CrashHandler);
1052     DoNullPointerDereference();
1053   }
1054   close(fds[1]);
1055   struct msghdr msg = {0};
1056   struct iovec iov;
1057   static const unsigned kCrashContextSize =
1058       sizeof(ExceptionHandler::CrashContext);
1059   char context[kCrashContextSize];
1060   char control[kControlMsgSize];
1061   iov.iov_base = context;
1062   iov.iov_len = kCrashContextSize;
1063   msg.msg_iov = &iov;
1064   msg.msg_iovlen = 1;
1065   msg.msg_control = control;
1066   msg.msg_controllen = kControlMsgSize;
1067 
1068   const ssize_t n = HANDLE_EINTR(recvmsg(fds[0], &msg, 0));
1069   ASSERT_EQ(static_cast<ssize_t>(kCrashContextSize), n);
1070   ASSERT_EQ(kControlMsgSize, msg.msg_controllen);
1071   ASSERT_EQ(static_cast<__typeof__(msg.msg_flags)>(0), msg.msg_flags);
1072   ASSERT_EQ(0, close(fds[0]));
1073 
1074   pid_t crashing_pid = -1;
1075   int signal_fd = -1;
1076   for (struct cmsghdr* hdr = CMSG_FIRSTHDR(&msg); hdr;
1077        hdr = CMSG_NXTHDR(&msg, hdr)) {
1078     if (hdr->cmsg_level != SOL_SOCKET)
1079       continue;
1080     if (hdr->cmsg_type == SCM_RIGHTS) {
1081       const unsigned len = hdr->cmsg_len -
1082           (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr);
1083       ASSERT_EQ(sizeof(int), len);
1084       signal_fd = *(reinterpret_cast<int*>(CMSG_DATA(hdr)));
1085     } else if (hdr->cmsg_type == SCM_CREDENTIALS) {
1086       const struct ucred* cred =
1087           reinterpret_cast<struct ucred*>(CMSG_DATA(hdr));
1088       crashing_pid = cred->pid;
1089     }
1090   }
1091 
1092   ASSERT_NE(crashing_pid, -1);
1093   ASSERT_NE(signal_fd, -1);
1094 
1095   AutoTempDir temp_dir;
1096   string templ = temp_dir.path() + "/exception-handler-unittest";
1097   ASSERT_TRUE(WriteMinidump(templ.c_str(), crashing_pid, context,
1098                             kCrashContextSize));
1099   static const char b = 0;
1100   ASSERT_EQ(1, (HANDLE_EINTR(write(signal_fd, &b, 1))));
1101   ASSERT_EQ(0, close(signal_fd));
1102 
1103   ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV));
1104 
1105   struct stat st;
1106   ASSERT_EQ(0, stat(templ.c_str(), &st));
1107   ASSERT_GT(st.st_size, 0);
1108   unlink(templ.c_str());
1109 }
1110 
1111 #endif  // !ADDRESS_SANITIZER
1112 
TEST(ExceptionHandlerTest,WriteMinidumpExceptionStream)1113 TEST(ExceptionHandlerTest, WriteMinidumpExceptionStream) {
1114   AutoTempDir temp_dir;
1115   ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, NULL,
1116                            NULL, false, -1);
1117   ASSERT_TRUE(handler.WriteMinidump());
1118 
1119   string minidump_path = handler.minidump_descriptor().path();
1120 
1121   // Read the minidump and check the exception stream.
1122   Minidump minidump(minidump_path);
1123   ASSERT_TRUE(minidump.Read());
1124   MinidumpException* exception = minidump.GetException();
1125   ASSERT_TRUE(exception);
1126   const MDRawExceptionStream* raw = exception->exception();
1127   ASSERT_TRUE(raw);
1128   EXPECT_EQ(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED,
1129             raw->exception_record.exception_code);
1130 }
1131 
TEST(ExceptionHandlerTest,GenerateMultipleDumpsWithFD)1132 TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithFD) {
1133   AutoTempDir temp_dir;
1134   string path;
1135   const int fd = CreateTMPFile(temp_dir.path(), &path);
1136   ExceptionHandler handler(MinidumpDescriptor(fd), NULL, NULL, NULL, false, -1);
1137   ASSERT_TRUE(handler.WriteMinidump());
1138   // Check by the size of the data written to the FD that a minidump was
1139   // generated.
1140   off_t size = lseek(fd, 0, SEEK_CUR);
1141   ASSERT_GT(size, 0);
1142 
1143   // Generate another minidump.
1144   ASSERT_TRUE(handler.WriteMinidump());
1145   size = lseek(fd, 0, SEEK_CUR);
1146   ASSERT_GT(size, 0);
1147 }
1148 
TEST(ExceptionHandlerTest,GenerateMultipleDumpsWithPath)1149 TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithPath) {
1150   AutoTempDir temp_dir;
1151   ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, NULL,
1152                            NULL, false, -1);
1153   ASSERT_TRUE(handler.WriteMinidump());
1154 
1155   const MinidumpDescriptor& minidump_1 = handler.minidump_descriptor();
1156   struct stat st;
1157   ASSERT_EQ(0, stat(minidump_1.path(), &st));
1158   ASSERT_GT(st.st_size, 0);
1159   string minidump_1_path(minidump_1.path());
1160   // Check it is a valid minidump.
1161   Minidump minidump1(minidump_1_path);
1162   ASSERT_TRUE(minidump1.Read());
1163   unlink(minidump_1.path());
1164 
1165   // Generate another minidump, it should go to a different file.
1166   ASSERT_TRUE(handler.WriteMinidump());
1167   const MinidumpDescriptor& minidump_2 = handler.minidump_descriptor();
1168   ASSERT_EQ(0, stat(minidump_2.path(), &st));
1169   ASSERT_GT(st.st_size, 0);
1170   string minidump_2_path(minidump_2.path());
1171   // Check it is a valid minidump.
1172   Minidump minidump2(minidump_2_path);
1173   ASSERT_TRUE(minidump2.Read());
1174   unlink(minidump_2.path());
1175 
1176   // 2 distinct files should be produced.
1177   ASSERT_STRNE(minidump_1_path.c_str(), minidump_2_path.c_str());
1178 }
1179 
1180 // Test that an additional memory region can be added to the minidump.
TEST(ExceptionHandlerTest,AdditionalMemory)1181 TEST(ExceptionHandlerTest, AdditionalMemory) {
1182   const uint32_t kMemorySize = sysconf(_SC_PAGESIZE);
1183 
1184   // Get some heap memory.
1185   uint8_t* memory = new uint8_t[kMemorySize];
1186   const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
1187   ASSERT_TRUE(memory);
1188 
1189   // Stick some data into the memory so the contents can be verified.
1190   for (uint32_t i = 0; i < kMemorySize; ++i) {
1191     memory[i] = i % 255;
1192   }
1193 
1194   AutoTempDir temp_dir;
1195   ExceptionHandler handler(
1196       MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
1197 
1198   // Add the memory region to the list of memory to be included.
1199   handler.RegisterAppMemory(memory, kMemorySize);
1200   handler.WriteMinidump();
1201 
1202   const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor();
1203 
1204   // Read the minidump. Ensure that the memory region is present
1205   Minidump minidump(minidump_desc.path());
1206   ASSERT_TRUE(minidump.Read());
1207 
1208   MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
1209   ASSERT_TRUE(dump_memory_list);
1210   const MinidumpMemoryRegion* region =
1211     dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
1212   ASSERT_TRUE(region);
1213 
1214   EXPECT_EQ(kMemoryAddress, region->GetBase());
1215   EXPECT_EQ(kMemorySize, region->GetSize());
1216 
1217   // Verify memory contents.
1218   EXPECT_EQ(0, memcmp(region->GetMemory(), memory, kMemorySize));
1219 
1220   delete[] memory;
1221 }
1222 
1223 // Test that a memory region that was previously registered
1224 // can be unregistered.
TEST(ExceptionHandlerTest,AdditionalMemoryRemove)1225 TEST(ExceptionHandlerTest, AdditionalMemoryRemove) {
1226   const uint32_t kMemorySize = sysconf(_SC_PAGESIZE);
1227 
1228   // Get some heap memory.
1229   uint8_t* memory = new uint8_t[kMemorySize];
1230   const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory);
1231   ASSERT_TRUE(memory);
1232 
1233   AutoTempDir temp_dir;
1234   ExceptionHandler handler(
1235       MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
1236 
1237   // Add the memory region to the list of memory to be included.
1238   handler.RegisterAppMemory(memory, kMemorySize);
1239 
1240   // ...and then remove it
1241   handler.UnregisterAppMemory(memory);
1242   handler.WriteMinidump();
1243 
1244   const MinidumpDescriptor& minidump_desc = handler.minidump_descriptor();
1245 
1246   // Read the minidump. Ensure that the memory region is not present.
1247   Minidump minidump(minidump_desc.path());
1248   ASSERT_TRUE(minidump.Read());
1249 
1250   MinidumpMemoryList* dump_memory_list = minidump.GetMemoryList();
1251   ASSERT_TRUE(dump_memory_list);
1252   const MinidumpMemoryRegion* region =
1253     dump_memory_list->GetMemoryRegionForAddress(kMemoryAddress);
1254   EXPECT_FALSE(region);
1255 
1256   delete[] memory;
1257 }
1258 
SimpleCallback(const MinidumpDescriptor & descriptor,void * context,bool succeeded)1259 static bool SimpleCallback(const MinidumpDescriptor& descriptor,
1260                            void* context,
1261                            bool succeeded) {
1262   string* filename = reinterpret_cast<string*>(context);
1263   *filename = descriptor.path();
1264   return true;
1265 }
1266 
TEST(ExceptionHandlerTest,WriteMinidumpForChild)1267 TEST(ExceptionHandlerTest, WriteMinidumpForChild) {
1268   int fds[2];
1269   ASSERT_NE(-1, pipe(fds));
1270 
1271   const pid_t child = fork();
1272   if (child == 0) {
1273     close(fds[1]);
1274     char b;
1275     HANDLE_EINTR(read(fds[0], &b, sizeof(b)));
1276     close(fds[0]);
1277     syscall(__NR_exit);
1278   }
1279   close(fds[0]);
1280 
1281   AutoTempDir temp_dir;
1282   string minidump_filename;
1283   ASSERT_TRUE(
1284     ExceptionHandler::WriteMinidumpForChild(child, child,
1285                                             temp_dir.path(), SimpleCallback,
1286                                             (void*)&minidump_filename));
1287 
1288   Minidump minidump(minidump_filename);
1289   ASSERT_TRUE(minidump.Read());
1290   // Check that the crashing thread is the main thread of |child|
1291   MinidumpException* exception = minidump.GetException();
1292   ASSERT_TRUE(exception);
1293   uint32_t thread_id;
1294   ASSERT_TRUE(exception->GetThreadID(&thread_id));
1295   EXPECT_EQ(child, static_cast<int32_t>(thread_id));
1296 
1297   const MDRawExceptionStream* raw = exception->exception();
1298   ASSERT_TRUE(raw);
1299   EXPECT_EQ(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED,
1300             raw->exception_record.exception_code);
1301 
1302   close(fds[1]);
1303   unlink(minidump_filename.c_str());
1304 }
1305