Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(422)

Side by Side Diff: crash_collector.cc

Issue 5814001: crash-reporter: Capture and send recent update_engine logs when it crashes (Closed) Base URL: http://git.chromium.org/git/crash-reporter.git@master
Patch Set: Respond to petkov review Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <fcntl.h> // For file creation modes.
9 #include <pwd.h> // For struct passwd. 9 #include <pwd.h> // For struct passwd.
10 #include <sys/types.h> // for mode_t. 10 #include <sys/types.h> // for mode_t.
11 #include <sys/wait.h> // For waitpid. 11 #include <sys/wait.h> // For waitpid.
12 #include <unistd.h> // For execv and fork. 12 #include <unistd.h> // For execv and fork.
13 13
14 #include <set> 14 #include <set>
15 15
16 #include "base/eintr_wrapper.h" 16 #include "base/eintr_wrapper.h"
17 #include "base/file_util.h" 17 #include "base/file_util.h"
18 #include "base/logging.h" 18 #include "base/logging.h"
19 #include "base/string_util.h" 19 #include "base/string_util.h"
20 #include "crash-reporter/system_logging.h" 20 #include "crash-reporter/system_logging.h"
21 21
22 static const char kDefaultUserName[] = "chronos"; 22 static const char kDefaultUserName[] = "chronos";
23 static const char kLsbRelease[] = "/etc/lsb-release"; 23 static const char kLsbRelease[] = "/etc/lsb-release";
24 static const char kShellPath[] = "/bin/sh";
24 static const char kSystemCrashPath[] = "/var/spool/crash"; 25 static const char kSystemCrashPath[] = "/var/spool/crash";
25 static const char kUserCrashPath[] = "/home/chronos/user/crash"; 26 static const char kUserCrashPath[] = "/home/chronos/user/crash";
26 27
27 // Directory mode of the user crash spool directory. 28 // Directory mode of the user crash spool directory.
28 static const mode_t kUserCrashPathMode = 0755; 29 static const mode_t kUserCrashPathMode = 0755;
29 30
30 // Directory mode of the system crash spool directory. 31 // Directory mode of the system crash spool directory.
31 static const mode_t kSystemCrashPathMode = 01755; 32 static const mode_t kSystemCrashPathMode = 01755;
32 33
33 static const uid_t kRootOwner = 0; 34 static const uid_t kRootOwner = 0;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 } 103 }
103 argv[arguments.size()] = NULL; 104 argv[arguments.size()] = NULL;
104 105
105 int pid = fork(); 106 int pid = fork();
106 if (pid < 0) { 107 if (pid < 0) {
107 logger_->LogError("Fork failed: %d", errno); 108 logger_->LogError("Fork failed: %d", errno);
108 return -1; 109 return -1;
109 } 110 }
110 111
111 if (pid == 0) { 112 if (pid == 0) {
112 int output_handle = HANDLE_EINTR(creat(output_file, 0700)); 113 int output_handle = HANDLE_EINTR(creat(output_file, 0600));
113 if (output_handle < 0) { 114 if (output_handle < 0) {
114 logger_->LogError("Could not create %s: %d", output_file, errno); 115 logger_->LogError("Could not create %s: %d", output_file, errno);
115 // Avoid exit() to avoid atexit handlers from parent. 116 // Avoid exit() to avoid atexit handlers from parent.
116 _exit(127); 117 _exit(127);
117 } 118 }
118 dup2(output_handle, 1); 119 dup2(output_handle, 1);
119 dup2(output_handle, 2); 120 dup2(output_handle, 2);
120 execv(argv[0], &argv[0]); 121 execv(argv[0], &argv[0]);
121 logger_->LogError("Exec failed: %d", errno); 122 logger_->LogError("Exec failed: %d", errno);
122 _exit(127); 123 _exit(127);
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 crash_directory.value().c_str(), 301 crash_directory.value().c_str(),
301 kMaxCrashDirectorySize); 302 kMaxCrashDirectorySize);
302 full = true; 303 full = true;
303 break; 304 break;
304 } 305 }
305 } 306 }
306 closedir(dir); 307 closedir(dir);
307 return !full; 308 return !full;
308 } 309 }
309 310
311 bool CrashCollector::IsCommentLine(const std::string &line) {
312 size_t found = line.find_first_not_of(" ");
313 return found != std::string::npos && line[found] == '#';
314 }
315
310 bool CrashCollector::ReadKeyValueFile( 316 bool CrashCollector::ReadKeyValueFile(
311 const FilePath &path, 317 const FilePath &path,
312 const char separator, 318 const char separator,
313 std::map<std::string, std::string> *dictionary) { 319 std::map<std::string, std::string> *dictionary) {
314 std::string contents; 320 std::string contents;
315 if (!file_util::ReadFileToString(path, &contents)) { 321 if (!file_util::ReadFileToString(path, &contents)) {
316 return false; 322 return false;
317 } 323 }
318 typedef std::vector<std::string> StringVector; 324 typedef std::vector<std::string> StringVector;
319 StringVector lines; 325 StringVector lines;
320 SplitString(contents, '\n', &lines); 326 SplitString(contents, '\n', &lines);
321 bool any_errors = false; 327 bool any_errors = false;
322 for (StringVector::iterator line = lines.begin(); line != lines.end(); 328 for (StringVector::iterator line = lines.begin(); line != lines.end();
323 ++line) { 329 ++line) {
324 // Allow empty strings. 330 // Allow empty strings.
325 if (line->empty()) 331 if (line->empty())
326 continue; 332 continue;
333 // Allow comment lines.
334 if (IsCommentLine(*line))
335 continue;
327 StringVector sides; 336 StringVector sides;
328 SplitString(*line, separator, &sides); 337 SplitString(*line, separator, &sides);
329 if (sides.size() != 2) { 338 if (sides.size() != 2) {
330 any_errors = true; 339 any_errors = true;
331 continue; 340 continue;
332 } 341 }
333 dictionary->insert(std::pair<std::string, std::string>(sides[0], sides[1])); 342 dictionary->insert(std::pair<std::string, std::string>(sides[0], sides[1]));
334 } 343 }
335 return !any_errors; 344 return !any_errors;
336 } 345 }
337 346
347 bool CrashCollector::GetLogContents(const FilePath &config_path,
348 const std::string &exec_name,
349 const FilePath &output_file) {
350 std::map<std::string, std::string> log_commands;
351 if (!ReadKeyValueFile(config_path, ':', &log_commands)) {
352 logger_->LogInfo("Unable to read log configuration file %s",
353 config_path.value().c_str());
354 return false;
355 }
356
357 if (log_commands.find(exec_name) == log_commands.end())
358 return false;
359
360 std::vector<const char *> command;
361 command.push_back(kShellPath);
362 command.push_back("-c");
363 std::string shell_command = log_commands[exec_name];
364 command.push_back(shell_command.c_str());
365
366 int fork_result = ForkExecAndPipe(command, output_file.value().c_str());
367 if (fork_result != 0) {
368 logger_->LogInfo("Running shell command %s failed with: %d",
369 shell_command.c_str(), fork_result);
370 return false;
371 }
372 return true;
373 }
374
338 void CrashCollector::AddCrashMetaData(const std::string &key, 375 void CrashCollector::AddCrashMetaData(const std::string &key,
339 const std::string &value) { 376 const std::string &value) {
340 extra_metadata_.append(StringPrintf("%s=%s\n", key.c_str(), value.c_str())); 377 extra_metadata_.append(StringPrintf("%s=%s\n", key.c_str(), value.c_str()));
341 } 378 }
342 379
343 void CrashCollector::WriteCrashMetaData(const FilePath &meta_path, 380 void CrashCollector::WriteCrashMetaData(const FilePath &meta_path,
344 const std::string &exec_name, 381 const std::string &exec_name,
345 const std::string &payload_path) { 382 const std::string &payload_path) {
346 std::map<std::string, std::string> contents; 383 std::map<std::string, std::string> contents;
347 if (!ReadKeyValueFile(FilePath(std::string(lsb_release_)), '=', &contents)) { 384 if (!ReadKeyValueFile(FilePath(std::string(lsb_release_)), '=', &contents)) {
(...skipping 17 matching lines...) Expand all
365 version.c_str(), 402 version.c_str(),
366 payload_path.c_str(), 403 payload_path.c_str(),
367 payload_size); 404 payload_size);
368 // We must use WriteNewFile instead of file_util::WriteFile as we 405 // 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 406 // do not want to write with root access to a symlink that an attacker
370 // might have created. 407 // might have created.
371 if (WriteNewFile(meta_path, meta_data.c_str(), meta_data.size()) < 0) { 408 if (WriteNewFile(meta_path, meta_data.c_str(), meta_data.size()) < 0) {
372 logger_->LogError("Unable to write %s", meta_path.value().c_str()); 409 logger_->LogError("Unable to write %s", meta_path.value().c_str());
373 } 410 }
374 } 411 }
OLDNEW
« no previous file with comments | « crash_collector.h ('k') | crash_collector_test.cc » ('j') | user_collector.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698