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

Side by Side Diff: crash_collector.cc

Issue 4603001: crash-reporter: Avoid writing through symlinks. (Closed) Base URL: http://git.chromium.org/git/crash-reporter.git@master
Patch Set: Respond to review Created 10 years, 1 month 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
« no previous file with comments | « crash_collector.h ('k') | crash_collector_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <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
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
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 }
OLDNEW
« no previous file with comments | « crash_collector.h ('k') | crash_collector_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698