| 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 | 4 |
| 5 #include "crash-reporter/crash_collector.h" | 5 #include "crash-reporter/crash_collector.h" |
| 6 | 6 |
| 7 #include <dirent.h> | 7 #include <dirent.h> |
| 8 #include <fcntl.h> // For file creation modes. |
| 8 #include <pwd.h> // For struct passwd. | 9 #include <pwd.h> // For struct passwd. |
| 9 #include <sys/types.h> // for mode_t. | 10 #include <sys/types.h> // for mode_t. |
| 11 #include <sys/wait.h> // For waitpid. |
| 12 #include <unistd.h> // For execv and fork. |
| 10 | 13 |
| 11 #include <set> | 14 #include <set> |
| 12 | 15 |
| 16 #include "base/eintr_wrapper.h" |
| 13 #include "base/file_util.h" | 17 #include "base/file_util.h" |
| 14 #include "base/logging.h" | 18 #include "base/logging.h" |
| 15 #include "base/string_util.h" | 19 #include "base/string_util.h" |
| 16 #include "crash-reporter/system_logging.h" | 20 #include "crash-reporter/system_logging.h" |
| 17 | 21 |
| 18 static const char kDefaultUserName[] = "chronos"; | 22 static const char kDefaultUserName[] = "chronos"; |
| 19 static const char kLsbRelease[] = "/etc/lsb-release"; | 23 static const char kLsbRelease[] = "/etc/lsb-release"; |
| 20 static const char kSystemCrashPath[] = "/var/spool/crash"; | 24 static const char kSystemCrashPath[] = "/var/spool/crash"; |
| 21 static const char kUserCrashPath[] = "/home/chronos/user/crash"; | 25 static const char kUserCrashPath[] = "/home/chronos/user/crash"; |
| 22 | 26 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 53 SystemLogging *logger) { | 57 SystemLogging *logger) { |
| 54 CHECK(count_crash_function != NULL); | 58 CHECK(count_crash_function != NULL); |
| 55 CHECK(is_feedback_allowed_function != NULL); | 59 CHECK(is_feedback_allowed_function != NULL); |
| 56 CHECK(logger != NULL); | 60 CHECK(logger != NULL); |
| 57 | 61 |
| 58 count_crash_function_ = count_crash_function; | 62 count_crash_function_ = count_crash_function; |
| 59 is_feedback_allowed_function_ = is_feedback_allowed_function; | 63 is_feedback_allowed_function_ = is_feedback_allowed_function; |
| 60 logger_ = logger; | 64 logger_ = logger; |
| 61 } | 65 } |
| 62 | 66 |
| 67 int CrashCollector::WriteNewFile(const FilePath &filename, |
| 68 const char *data, |
| 69 int size) { |
| 70 int fd = HANDLE_EINTR(open(filename.value().c_str(), |
| 71 O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666)); |
| 72 if (fd < 0) { |
| 73 return -1; |
| 74 } |
| 75 |
| 76 int rv = file_util::WriteFileDescriptor(fd, data, size); |
| 77 HANDLE_EINTR(close(fd)); |
| 78 return rv; |
| 79 } |
| 80 |
| 81 int CrashCollector::ForkExecAndPipe(std::vector<const char *> &arguments, |
| 82 const char *output_file) { |
| 83 // Copy off a writeable version of arguments. |
| 84 scoped_array<char*> argv(new char *[arguments.size() + 1]); |
| 85 int total_args_size = 0; |
| 86 for (size_t i = 0; i < arguments.size(); ++i) { |
| 87 if (arguments[i] == NULL) { |
| 88 logger_->LogError("Bad parameter"); |
| 89 return -1; |
| 90 } |
| 91 total_args_size += strlen(arguments[i]) + 1; |
| 92 } |
| 93 scoped_array<char> buffer(new char[total_args_size]); |
| 94 char *buffer_pointer = &buffer[0]; |
| 95 |
| 96 for (size_t i = 0; i < arguments.size(); ++i) { |
| 97 argv[i] = buffer_pointer; |
| 98 strcpy(buffer_pointer, arguments[i]); |
| 99 buffer_pointer += strlen(arguments[i]); |
| 100 *buffer_pointer = '\0'; |
| 101 ++buffer_pointer; |
| 102 } |
| 103 argv[arguments.size()] = NULL; |
| 104 |
| 105 int pid = fork(); |
| 106 if (pid < 0) { |
| 107 logger_->LogError("Fork failed: %d", errno); |
| 108 return -1; |
| 109 } |
| 110 |
| 111 if (pid == 0) { |
| 112 int output_handle = HANDLE_EINTR(creat(output_file, 0700)); |
| 113 if (output_handle < 0) { |
| 114 logger_->LogError("Could not create %s: %d", output_file, errno); |
| 115 // Avoid exit() to avoid atexit handlers from parent. |
| 116 _exit(127); |
| 117 } |
| 118 dup2(output_handle, 1); |
| 119 dup2(output_handle, 2); |
| 120 execv(argv[0], &argv[0]); |
| 121 logger_->LogError("Exec failed: %d", errno); |
| 122 _exit(127); |
| 123 } |
| 124 |
| 125 int status = 0; |
| 126 if (HANDLE_EINTR(waitpid(pid, &status, 0)) < 0) { |
| 127 logger_->LogError("Problem waiting for pid: %d", errno); |
| 128 return -1; |
| 129 } |
| 130 if (!WIFEXITED(status)) { |
| 131 logger_->LogError("Process did not exit normally: %d", status); |
| 132 return -1; |
| 133 } |
| 134 return WEXITSTATUS(status); |
| 135 } |
| 136 |
| 63 std::string CrashCollector::Sanitize(const std::string &name) { | 137 std::string CrashCollector::Sanitize(const std::string &name) { |
| 64 std::string result = name; | 138 std::string result = name; |
| 65 for (size_t i = 0; i < name.size(); ++i) { | 139 for (size_t i = 0; i < name.size(); ++i) { |
| 66 if (!isalnum(result[i]) && result[i] != '_') | 140 if (!isalnum(result[i]) && result[i] != '_') |
| 67 result[i] = '_'; | 141 result[i] = '_'; |
| 68 } | 142 } |
| 69 return result; | 143 return result; |
| 70 } | 144 } |
| 71 | 145 |
| 72 std::string CrashCollector::FormatDumpBasename(const std::string &exec_name, | 146 std::string CrashCollector::FormatDumpBasename(const std::string &exec_name, |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 std::string meta_data = StringPrintf("%sexec_name=%s\n" | 358 std::string meta_data = StringPrintf("%sexec_name=%s\n" |
| 285 "ver=%s\n" | 359 "ver=%s\n" |
| 286 "payload=%s\n" | 360 "payload=%s\n" |
| 287 "payload_size=%lld\n" | 361 "payload_size=%lld\n" |
| 288 "done=1\n", | 362 "done=1\n", |
| 289 extra_metadata_.c_str(), | 363 extra_metadata_.c_str(), |
| 290 exec_name.c_str(), | 364 exec_name.c_str(), |
| 291 version.c_str(), | 365 version.c_str(), |
| 292 payload_path.c_str(), | 366 payload_path.c_str(), |
| 293 payload_size); | 367 payload_size); |
| 294 if (!file_util::WriteFile(meta_path, meta_data.c_str(), meta_data.size())) { | 368 // We must use WriteNewFile instead of file_util::WriteFile as we |
| 369 // do not want to write with root access to a symlink that an attacker |
| 370 // might have created. |
| 371 if (WriteNewFile(meta_path, meta_data.c_str(), meta_data.size()) < 0) { |
| 295 logger_->LogError("Unable to write %s", meta_path.value().c_str()); | 372 logger_->LogError("Unable to write %s", meta_path.value().c_str()); |
| 296 } | 373 } |
| 297 } | 374 } |
| OLD | NEW |