| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // |
| 5 // Simple wrapper and basic configuration of Google breakpad. We try |
| 6 // to avoid using any unnecessary code (like libbase) to make it as |
| 7 // non-intrusive as possible to link in this library. |
| 4 | 8 |
| 5 #include <errno.h> | 9 #include <errno.h> |
| 6 #include <pwd.h> | 10 #include <pwd.h> |
| 11 #include <stddef.h> |
| 7 #include <sys/stat.h> | 12 #include <sys/stat.h> |
| 8 #include <sys/types.h> | 13 #include <sys/types.h> |
| 9 #include <unistd.h> | 14 #include <unistd.h> |
| 10 | 15 |
| 11 #include "base/file_path.h" | |
| 12 #include "base/file_util.h" | |
| 13 #include "base/logging.h" | |
| 14 #include "client/linux/handler/exception_handler.h" | 16 #include "client/linux/handler/exception_handler.h" |
| 15 #include "common/linux/linux_libc_support.h" | 17 #include "common/linux/linux_libc_support.h" |
| 16 #include "common/linux/linux_syscall_support.h" | 18 #include "common/linux/linux_syscall_support.h" |
| 17 #include "crash/crash_dumper.h" | 19 #include "crash/crash_dumper.h" |
| 18 | 20 |
| 19 // Define sys_mkdir (sys_open passes mode_t as int, so we do too). | 21 // Define sys_mkdir (sys_open passes mode_t as int, so we do too). |
| 20 LSS_INLINE _syscall2(int, mkdir, const char *, pathname, int, mode); | 22 LSS_INLINE _syscall2(int, mkdir, const char *, pathname, int, mode); |
| 21 | 23 |
| 22 static const char kDefaultUser[] = "chronos"; | 24 static const char kDefaultUser[] = "chronos"; |
| 23 static const char kSystemCrashParentPath[] = "/var/spool"; | 25 static const char kSystemCrashParentPath[] = "/var/spool"; |
| 24 static const char kSystemCrashPath[] = "/var/spool/crash"; | 26 static const char kSystemCrashPath[] = "/var/spool/crash"; |
| 25 static const char kUserCrashParentPath[] = "/home/chronos/user"; | 27 static const char kUserCrashParentPath[] = "/home/chronos/user"; |
| 26 static const char kUserCrashPath[] = "/home/chronos/user/crash"; | 28 static const char kUserCrashPath[] = "/home/chronos/user/crash"; |
| 27 | 29 |
| 28 // Pointers to paths, set when crash dumping is enabled. | 30 // Pointers to paths, set when crash dumping is enabled. |
| 29 static const char *s_crash_path; | 31 static const char *s_crash_path; |
| 30 static const char *s_crash_parent_path; | 32 static const char *s_crash_parent_path; |
| 31 static mode_t s_dump_directory_mode; | 33 static mode_t s_dump_directory_mode; |
| 32 | 34 |
| 33 static bool s_any_crashes_occurred = false; | 35 static bool s_any_crashes_occurred = false; |
| 34 static scoped_ptr<google_breakpad::ExceptionHandler> s_breakpad_handler; | 36 static google_breakpad::ExceptionHandler *s_breakpad_handler; |
| 35 | 37 |
| 36 static bool s_enabled = false; | 38 static bool s_enabled = false; |
| 37 | 39 |
| 40 #define CHECK_CONDITION(_cond, _message) \ |
| 41 do { if (!(_cond)) { fputs(_message, stderr); abort(); } } while(false) |
| 42 |
| 43 // This static object will cause anything that links in this object to get |
| 44 // crash handling for the duration of this file's scope. |
| 45 static CrashDumper g_crash_dumper; |
| 46 |
| 38 | 47 |
| 39 // Prepare the crash path. Must avoid allocating memory. | 48 // Prepare the crash path. Must avoid allocating memory. |
| 40 static bool PrepareCrashPath() { | 49 static bool PrepareCrashPath() { |
| 41 struct kernel_stat buf; | 50 struct kernel_stat buf; |
| 42 if (sys_stat(s_crash_path, &buf) < 0) { | 51 if (sys_stat(s_crash_path, &buf) < 0) { |
| 43 // Dump directory does not exist, so create it and its parent now, | 52 // Dump directory does not exist, so create it and its parent now, |
| 44 // at the time of the crash. | 53 // at the time of the crash. |
| 45 sys_mkdir(s_crash_parent_path, 755); | 54 sys_mkdir(s_crash_parent_path, 755); |
| 46 sys_mkdir(s_crash_path, s_dump_directory_mode); | 55 sys_mkdir(s_crash_path, s_dump_directory_mode); |
| 47 } | 56 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 71 if (getpwuid_r(geteuid(), &passwd_storage, storage, sizeof(storage), | 80 if (getpwuid_r(geteuid(), &passwd_storage, storage, sizeof(storage), |
| 72 &passwd_result) != 0 || passwd_result == NULL) { | 81 &passwd_result) != 0 || passwd_result == NULL) { |
| 73 return false; | 82 return false; |
| 74 } | 83 } |
| 75 | 84 |
| 76 *result = passwd_result->pw_name; | 85 *result = passwd_result->pw_name; |
| 77 return true; | 86 return true; |
| 78 } | 87 } |
| 79 | 88 |
| 80 void CrashDumper::Enable() { | 89 void CrashDumper::Enable() { |
| 81 CHECK(!s_enabled) << "Crash handling already enabled"; | 90 CHECK_CONDITION(!s_enabled, "Crash handling already enabled"); |
| 82 | 91 |
| 83 std::string name; | 92 std::string name; |
| 84 CHECK(GetEffectiveUser(&name)) | 93 CHECK_CONDITION(GetEffectiveUser(&name), |
| 85 << "getpwuid_r failed - " << errno | 94 "getpwuid_r failed, cannot enable crash reporting"); |
| 86 << " - crash reporting cannot be enabled"; | |
| 87 | 95 |
| 88 if (name == kDefaultUser) { | 96 if (name == kDefaultUser) { |
| 89 // Crashes as "chronos" when the user is not yet logged in will | 97 // Crashes as "chronos" when the user is not yet logged in will |
| 90 // still be recorded to /home/chronos/user/crash in the | 98 // still be recorded to /home/chronos/user/crash in the |
| 91 // stateful partition (outside cryptohome). These will eventually | 99 // stateful partition (outside cryptohome). These will eventually |
| 92 // be uploaded when no user is logged in. | 100 // be uploaded when no user is logged in. |
| 93 s_crash_path = kUserCrashPath; | 101 s_crash_path = kUserCrashPath; |
| 94 s_crash_parent_path = kUserCrashParentPath; | 102 s_crash_parent_path = kUserCrashParentPath; |
| 95 s_dump_directory_mode = 0755; | 103 s_dump_directory_mode = 0755; |
| 96 } else { | 104 } else { |
| 97 s_crash_path = kSystemCrashPath; | 105 s_crash_path = kSystemCrashPath; |
| 98 s_crash_parent_path = kSystemCrashParentPath; | 106 s_crash_parent_path = kSystemCrashParentPath; |
| 99 // Make the dump directory sticky so any UID can write to | 107 // Make the dump directory sticky so any UID can write to |
| 100 // it but not remove another UID's crashes. | 108 // it but not remove another UID's crashes. |
| 101 s_dump_directory_mode = 01777; | 109 s_dump_directory_mode = 01777; |
| 102 } | 110 } |
| 103 | 111 |
| 104 CHECK(PrepareCrashPath()) << "Unable to create path " << s_crash_path; | 112 CHECK_CONDITION(PrepareCrashPath(), "Unable to create crash path"); |
| 105 | 113 |
| 106 // Begin collecting crashes | 114 // Begin collecting crashes |
| 107 s_breakpad_handler.reset(new google_breakpad::ExceptionHandler( | 115 s_breakpad_handler = new google_breakpad::ExceptionHandler( |
| 108 s_crash_path, | 116 s_crash_path, |
| 109 FilterCallback, | 117 FilterCallback, |
| 110 NULL, // No minidump callback - sending happens asynchronously to writing | 118 NULL, // No minidump callback - sending happens asynchronously to writing |
| 111 NULL, // No callback context necessary | 119 NULL, // No callback context necessary |
| 112 true)); // Install handler now. | 120 true); // Install handler now. |
| 113 | 121 |
| 114 s_enabled = true; | 122 s_enabled = true; |
| 115 } | 123 } |
| 116 | 124 |
| 117 bool CrashDumper::IsEnabled() { | 125 bool CrashDumper::IsEnabled() { |
| 118 return s_enabled; | 126 return s_enabled; |
| 119 } | 127 } |
| 120 | 128 |
| 121 void CrashDumper::Disable() { | 129 void CrashDumper::Disable() { |
| 122 CHECK(s_enabled) << "Crash handling was not enabled"; | 130 CHECK_CONDITION(s_enabled, "Crash handling was not enabled"); |
| 123 s_breakpad_handler.reset(NULL); | 131 delete s_breakpad_handler; |
| 132 s_breakpad_handler = NULL; |
| 124 s_crash_path = NULL; | 133 s_crash_path = NULL; |
| 125 s_crash_parent_path = NULL; | 134 s_crash_parent_path = NULL; |
| 126 s_enabled = false; | 135 s_enabled = false; |
| 127 } | 136 } |
| OLD | NEW |