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/user_collector.h" | 5 #include "crash-reporter/user_collector.h" |
6 | 6 |
7 #include <fcntl.h> // For creat. | |
8 #include <grp.h> // For struct group. | 7 #include <grp.h> // For struct group. |
9 #include <pwd.h> // For struct passwd. | 8 #include <pwd.h> // For struct passwd. |
10 #include <sys/types.h> // For getpwuid_r, getgrnam_r, WEXITSTATUS. | 9 #include <sys/types.h> // For getpwuid_r, getgrnam_r, WEXITSTATUS. |
11 #include <sys/wait.h> // For waitpid. | |
12 #include <unistd.h> // For execv and fork. | |
13 | 10 |
14 #include <string> | 11 #include <string> |
15 #include <vector> | 12 #include <vector> |
16 | 13 |
17 #include "base/eintr_wrapper.h" | |
18 #include "base/file_util.h" | 14 #include "base/file_util.h" |
19 #include "base/logging.h" | 15 #include "base/logging.h" |
20 #include "base/string_util.h" | 16 #include "base/string_util.h" |
21 #include "crash-reporter/system_logging.h" | 17 #include "crash-reporter/system_logging.h" |
22 #include "gflags/gflags.h" | 18 #include "gflags/gflags.h" |
23 | 19 |
24 #pragma GCC diagnostic ignored "-Wstrict-aliasing" | 20 #pragma GCC diagnostic ignored "-Wstrict-aliasing" |
25 DEFINE_bool(core2md_failure_test, false, "Core2md failure test"); | 21 DEFINE_bool(core2md_failure_test, false, "Core2md failure test"); |
26 DEFINE_bool(directory_failure_test, false, "Spool directory failure test"); | 22 DEFINE_bool(directory_failure_test, false, "Spool directory failure test"); |
27 DEFINE_string(filter_in, "", | 23 DEFINE_string(filter_in, "", |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 const std::string &exec) { | 165 const std::string &exec) { |
170 FilePath crash_path; | 166 FilePath crash_path; |
171 logger_->LogInfo("Writing conversion problems as separate crash report."); | 167 logger_->LogInfo("Writing conversion problems as separate crash report."); |
172 if (!GetCreatedCrashDirectoryByEuid(0, &crash_path, NULL)) { | 168 if (!GetCreatedCrashDirectoryByEuid(0, &crash_path, NULL)) { |
173 logger_->LogError("Could not even get log directory; out of space?"); | 169 logger_->LogError("Could not even get log directory; out of space?"); |
174 return; | 170 return; |
175 } | 171 } |
176 std::string dump_basename = FormatDumpBasename(exec, time(NULL), pid); | 172 std::string dump_basename = FormatDumpBasename(exec, time(NULL), pid); |
177 FilePath log_path = GetCrashPath(crash_path, dump_basename, "log"); | 173 FilePath log_path = GetCrashPath(crash_path, dump_basename, "log"); |
178 FilePath meta_path = GetCrashPath(crash_path, dump_basename, "meta"); | 174 FilePath meta_path = GetCrashPath(crash_path, dump_basename, "meta"); |
179 file_util::WriteFile(log_path, | 175 // We must use WriteNewFile instead of file_util::WriteFile as we do |
180 error_log_.data(), | 176 // not want to write with root access to a symlink that an attacker |
181 error_log_.length()); | 177 // might have created. |
| 178 WriteNewFile(log_path, error_log_.data(), error_log_.length()); |
182 AddCrashMetaData("sig", kCollectionErrorSignature); | 179 AddCrashMetaData("sig", kCollectionErrorSignature); |
183 WriteCrashMetaData(meta_path, exec, log_path.value()); | 180 WriteCrashMetaData(meta_path, exec, log_path.value()); |
184 } | 181 } |
185 | 182 |
186 bool UserCollector::CopyOffProcFiles(pid_t pid, | 183 bool UserCollector::CopyOffProcFiles(pid_t pid, |
187 const FilePath &container_dir) { | 184 const FilePath &container_dir) { |
188 if (!file_util::CreateDirectory(container_dir)) { | 185 if (!file_util::CreateDirectory(container_dir)) { |
189 LogCollectionError(StringPrintf("Could not create %s", | 186 LogCollectionError(StringPrintf("Could not create %s", |
190 container_dir.value().c_str())); | 187 container_dir.value().c_str())); |
191 return false; | 188 return false; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 if (file_util::CopyFile(stdin_path, core_path)) { | 245 if (file_util::CopyFile(stdin_path, core_path)) { |
249 return true; | 246 return true; |
250 } | 247 } |
251 | 248 |
252 LogCollectionError("Could not write core file"); | 249 LogCollectionError("Could not write core file"); |
253 // If the file system was full, make sure we remove any remnants. | 250 // If the file system was full, make sure we remove any remnants. |
254 file_util::Delete(core_path, false); | 251 file_util::Delete(core_path, false); |
255 return false; | 252 return false; |
256 } | 253 } |
257 | 254 |
258 int UserCollector::ForkExecAndPipe(std::vector<const char *> &arguments, | |
259 const char *output_file) { | |
260 // Copy off a writeable version of arguments. | |
261 scoped_array<char*> argv(new char *[arguments.size() + 1]); | |
262 int total_args_size = 0; | |
263 for (size_t i = 0; i < arguments.size(); ++i) { | |
264 if (arguments[i] == NULL) { | |
265 logger_->LogError("Bad parameter"); | |
266 return -1; | |
267 } | |
268 total_args_size += strlen(arguments[i]) + 1; | |
269 } | |
270 scoped_array<char> buffer(new char[total_args_size]); | |
271 char *buffer_pointer = &buffer[0]; | |
272 | |
273 for (size_t i = 0; i < arguments.size(); ++i) { | |
274 argv[i] = buffer_pointer; | |
275 strcpy(buffer_pointer, arguments[i]); | |
276 buffer_pointer += strlen(arguments[i]); | |
277 *buffer_pointer = '\0'; | |
278 ++buffer_pointer; | |
279 } | |
280 argv[arguments.size()] = NULL; | |
281 | |
282 int pid = fork(); | |
283 if (pid < 0) { | |
284 logger_->LogError("Fork failed: %d", errno); | |
285 return -1; | |
286 } | |
287 | |
288 if (pid == 0) { | |
289 int output_handle = creat(output_file, 0700); | |
290 if (output_handle < 0) { | |
291 logger_->LogError("Could not create %s: %d", output_file, errno); | |
292 // Avoid exit() to avoid atexit handlers from parent. | |
293 _exit(127); | |
294 } | |
295 dup2(output_handle, 1); | |
296 dup2(output_handle, 2); | |
297 execv(argv[0], &argv[0]); | |
298 logger_->LogError("Exec failed: %d", errno); | |
299 _exit(127); | |
300 } | |
301 | |
302 int status = 0; | |
303 if (HANDLE_EINTR(waitpid(pid, &status, 0)) < 0) { | |
304 logger_->LogError("Problem waiting for pid: %d", errno); | |
305 return -1; | |
306 } | |
307 if (!WIFEXITED(status)) { | |
308 logger_->LogError("Process did not exit normally: %d", status); | |
309 return -1; | |
310 } | |
311 return WEXITSTATUS(status); | |
312 } | |
313 | |
314 bool UserCollector::RunCoreToMinidump(const FilePath &core_path, | 255 bool UserCollector::RunCoreToMinidump(const FilePath &core_path, |
315 const FilePath &procfs_directory, | 256 const FilePath &procfs_directory, |
316 const FilePath &minidump_path, | 257 const FilePath &minidump_path, |
317 const FilePath &temp_directory) { | 258 const FilePath &temp_directory) { |
318 FilePath output_path = temp_directory.Append("output"); | 259 FilePath output_path = temp_directory.Append("output"); |
319 std::vector<const char *> core2md_arguments; | 260 std::vector<const char *> core2md_arguments; |
320 core2md_arguments.push_back(kCoreToMinidumpConverterPath); | 261 core2md_arguments.push_back(kCoreToMinidumpConverterPath); |
321 core2md_arguments.push_back(core_path.value().c_str()); | 262 core2md_arguments.push_back(core_path.value().c_str()); |
322 core2md_arguments.push_back(procfs_directory.value().c_str()); | 263 core2md_arguments.push_back(procfs_directory.value().c_str()); |
323 core2md_arguments.push_back(minidump_path.value().c_str()); | 264 core2md_arguments.push_back(minidump_path.value().c_str()); |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 if (!ConvertAndEnqueueCrash(pid, exec, &out_of_capacity)) { | 394 if (!ConvertAndEnqueueCrash(pid, exec, &out_of_capacity)) { |
454 if (!out_of_capacity) | 395 if (!out_of_capacity) |
455 EnqueueCollectionErrorLog(pid, exec); | 396 EnqueueCollectionErrorLog(pid, exec); |
456 return false; | 397 return false; |
457 } | 398 } |
458 } | 399 } |
459 } | 400 } |
460 | 401 |
461 return true; | 402 return true; |
462 } | 403 } |
OLD | NEW |