| Index: crash_collector.cc
|
| diff --git a/crash_collector.cc b/crash_collector.cc
|
| index 1e2cd1abdd66e016993540fecc3979328badad72..7abe2a58073c66b0b651392e01e6341ce093a59a 100644
|
| --- a/crash_collector.cc
|
| +++ b/crash_collector.cc
|
| @@ -5,11 +5,15 @@
|
| #include "crash-reporter/crash_collector.h"
|
|
|
| #include <dirent.h>
|
| +#include <fcntl.h> // For file creation modes.
|
| #include <pwd.h> // For struct passwd.
|
| #include <sys/types.h> // for mode_t.
|
| +#include <sys/wait.h> // For waitpid.
|
| +#include <unistd.h> // For execv and fork.
|
|
|
| #include <set>
|
|
|
| +#include "base/eintr_wrapper.h"
|
| #include "base/file_util.h"
|
| #include "base/logging.h"
|
| #include "base/string_util.h"
|
| @@ -60,6 +64,76 @@ void CrashCollector::Initialize(
|
| logger_ = logger;
|
| }
|
|
|
| +int CrashCollector::WriteNewFile(const FilePath &filename,
|
| + const char *data,
|
| + int size) {
|
| + int fd = HANDLE_EINTR(open(filename.value().c_str(),
|
| + O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666));
|
| + if (fd < 0) {
|
| + return -1;
|
| + }
|
| +
|
| + int rv = file_util::WriteFileDescriptor(fd, data, size);
|
| + HANDLE_EINTR(close(fd));
|
| + return rv;
|
| +}
|
| +
|
| +int CrashCollector::ForkExecAndPipe(std::vector<const char *> &arguments,
|
| + const char *output_file) {
|
| + // Copy off a writeable version of arguments.
|
| + scoped_array<char*> argv(new char *[arguments.size() + 1]);
|
| + int total_args_size = 0;
|
| + for (size_t i = 0; i < arguments.size(); ++i) {
|
| + if (arguments[i] == NULL) {
|
| + logger_->LogError("Bad parameter");
|
| + return -1;
|
| + }
|
| + total_args_size += strlen(arguments[i]) + 1;
|
| + }
|
| + scoped_array<char> buffer(new char[total_args_size]);
|
| + char *buffer_pointer = &buffer[0];
|
| +
|
| + for (size_t i = 0; i < arguments.size(); ++i) {
|
| + argv[i] = buffer_pointer;
|
| + strcpy(buffer_pointer, arguments[i]);
|
| + buffer_pointer += strlen(arguments[i]);
|
| + *buffer_pointer = '\0';
|
| + ++buffer_pointer;
|
| + }
|
| + argv[arguments.size()] = NULL;
|
| +
|
| + int pid = fork();
|
| + if (pid < 0) {
|
| + logger_->LogError("Fork failed: %d", errno);
|
| + return -1;
|
| + }
|
| +
|
| + if (pid == 0) {
|
| + int output_handle = HANDLE_EINTR(creat(output_file, 0700));
|
| + if (output_handle < 0) {
|
| + logger_->LogError("Could not create %s: %d", output_file, errno);
|
| + // Avoid exit() to avoid atexit handlers from parent.
|
| + _exit(127);
|
| + }
|
| + dup2(output_handle, 1);
|
| + dup2(output_handle, 2);
|
| + execv(argv[0], &argv[0]);
|
| + logger_->LogError("Exec failed: %d", errno);
|
| + _exit(127);
|
| + }
|
| +
|
| + int status = 0;
|
| + if (HANDLE_EINTR(waitpid(pid, &status, 0)) < 0) {
|
| + logger_->LogError("Problem waiting for pid: %d", errno);
|
| + return -1;
|
| + }
|
| + if (!WIFEXITED(status)) {
|
| + logger_->LogError("Process did not exit normally: %d", status);
|
| + return -1;
|
| + }
|
| + return WEXITSTATUS(status);
|
| +}
|
| +
|
| std::string CrashCollector::Sanitize(const std::string &name) {
|
| std::string result = name;
|
| for (size_t i = 0; i < name.size(); ++i) {
|
| @@ -291,7 +365,10 @@ void CrashCollector::WriteCrashMetaData(const FilePath &meta_path,
|
| version.c_str(),
|
| payload_path.c_str(),
|
| payload_size);
|
| - if (!file_util::WriteFile(meta_path, meta_data.c_str(), meta_data.size())) {
|
| + // We must use WriteNewFile instead of file_util::WriteFile as we
|
| + // do not want to write with root access to a symlink that an attacker
|
| + // might have created.
|
| + if (WriteNewFile(meta_path, meta_data.c_str(), meta_data.size()) < 0) {
|
| logger_->LogError("Unable to write %s", meta_path.value().c_str());
|
| }
|
| }
|
|
|