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/kernel_collector.h" | 5 #include "crash-reporter/kernel_collector.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
10 #include "crash-reporter/system_logging.h" | |
11 | 10 |
12 const char KernelCollector::kClearingSequence[] = " "; | 11 const char KernelCollector::kClearingSequence[] = " "; |
13 static const char kDefaultKernelStackSignature[] = | 12 static const char kDefaultKernelStackSignature[] = |
14 "kernel-UnspecifiedStackSignature"; | 13 "kernel-UnspecifiedStackSignature"; |
15 static const char kKernelExecName[] = "kernel"; | 14 static const char kKernelExecName[] = "kernel"; |
16 const pid_t kKernelPid = 0; | 15 const pid_t kKernelPid = 0; |
17 static const char kKernelSignatureKey[] = "sig"; | 16 static const char kKernelSignatureKey[] = "sig"; |
18 // Byte length of maximum human readable portion of a kernel crash signature. | 17 // Byte length of maximum human readable portion of a kernel crash signature. |
19 static const int kMaxHumanStringLength = 40; | 18 static const int kMaxHumanStringLength = 40; |
20 static const char kPreservedDumpPath[] = "/sys/kernel/debug/preserved/kcrash"; | 19 static const char kPreservedDumpPath[] = "/sys/kernel/debug/preserved/kcrash"; |
(...skipping 13 matching lines...) Expand all Loading... |
34 } | 33 } |
35 | 34 |
36 void KernelCollector::OverridePreservedDumpPath(const FilePath &file_path) { | 35 void KernelCollector::OverridePreservedDumpPath(const FilePath &file_path) { |
37 preserved_dump_path_ = file_path; | 36 preserved_dump_path_ = file_path; |
38 } | 37 } |
39 | 38 |
40 bool KernelCollector::LoadPreservedDump(std::string *contents) { | 39 bool KernelCollector::LoadPreservedDump(std::string *contents) { |
41 // clear contents since ReadFileToString actually appends to the string. | 40 // clear contents since ReadFileToString actually appends to the string. |
42 contents->clear(); | 41 contents->clear(); |
43 if (!file_util::ReadFileToString(preserved_dump_path_, contents)) { | 42 if (!file_util::ReadFileToString(preserved_dump_path_, contents)) { |
44 logger_->LogError("Unable to read %s", | 43 LOG(ERROR) << "Unable to read " << preserved_dump_path_.value(); |
45 preserved_dump_path_.value().c_str()); | |
46 return false; | 44 return false; |
47 } | 45 } |
48 return true; | 46 return true; |
49 } | 47 } |
50 | 48 |
51 bool KernelCollector::Enable() { | 49 bool KernelCollector::Enable() { |
52 if (!file_util::PathExists(preserved_dump_path_)) { | 50 if (!file_util::PathExists(preserved_dump_path_)) { |
53 logger_->LogWarning("Kernel does not support crash dumping"); | 51 LOG(WARNING) << "Kernel does not support crash dumping"; |
54 return false; | 52 return false; |
55 } | 53 } |
56 | 54 |
57 // To enable crashes, we will eventually need to set | 55 // To enable crashes, we will eventually need to set |
58 // the chnv bit in BIOS, but it does not yet work. | 56 // the chnv bit in BIOS, but it does not yet work. |
59 logger_->LogInfo("Enabling kernel crash handling"); | 57 LOG(INFO) << "Enabling kernel crash handling"; |
60 is_enabled_ = true; | 58 is_enabled_ = true; |
61 return true; | 59 return true; |
62 } | 60 } |
63 | 61 |
64 bool KernelCollector::ClearPreservedDump() { | 62 bool KernelCollector::ClearPreservedDump() { |
65 // It is necessary to write at least one byte to the kcrash file for | 63 // It is necessary to write at least one byte to the kcrash file for |
66 // the log to actually be cleared. | 64 // the log to actually be cleared. |
67 if (file_util::WriteFile( | 65 if (file_util::WriteFile( |
68 preserved_dump_path_, | 66 preserved_dump_path_, |
69 kClearingSequence, | 67 kClearingSequence, |
70 strlen(kClearingSequence)) != strlen(kClearingSequence)) { | 68 strlen(kClearingSequence)) != strlen(kClearingSequence)) { |
71 logger_->LogError("Failed to clear kernel crash dump"); | 69 LOG(ERROR) << "Failed to clear kernel crash dump"; |
72 return false; | 70 return false; |
73 } | 71 } |
74 logger_->LogInfo("Cleared kernel crash diagnostics"); | 72 LOG(INFO) << "Cleared kernel crash diagnostics"; |
75 return true; | 73 return true; |
76 } | 74 } |
77 | 75 |
78 // Hash a string to a number. We define our own hash function to not | 76 // Hash a string to a number. We define our own hash function to not |
79 // be dependent on a C++ library that might change. This function | 77 // be dependent on a C++ library that might change. This function |
80 // uses basically the same approach as tr1/functional_hash.h but with | 78 // uses basically the same approach as tr1/functional_hash.h but with |
81 // a larger prime number (16127 vs 131). | 79 // a larger prime number (16127 vs 131). |
82 static unsigned HashString(const std::string &input) { | 80 static unsigned HashString(const std::string &input) { |
83 unsigned hash = 0; | 81 unsigned hash = 0; |
84 for (size_t i = 0; i < input.length(); ++i) | 82 for (size_t i = 0; i < input.length(); ++i) |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 if (kernel_dump.empty()) { | 247 if (kernel_dump.empty()) { |
250 return false; | 248 return false; |
251 } | 249 } |
252 std::string signature; | 250 std::string signature; |
253 if (!ComputeKernelStackSignature(kernel_dump, &signature, false)) { | 251 if (!ComputeKernelStackSignature(kernel_dump, &signature, false)) { |
254 signature = kDefaultKernelStackSignature; | 252 signature = kDefaultKernelStackSignature; |
255 } | 253 } |
256 | 254 |
257 bool feedback = is_feedback_allowed_function_(); | 255 bool feedback = is_feedback_allowed_function_(); |
258 | 256 |
259 logger_->LogInfo("Received prior crash notification from " | 257 LOG(INFO) << "Received prior crash notification from " |
260 "kernel (signature %s) (%s)", | 258 << "kernel (signature " << signature << ") (" |
261 signature.c_str(), | 259 << (feedback ? "handling" : "ignoring - no consent") << ")"; |
262 feedback ? "handling" : "ignoring - no consent"); | |
263 | 260 |
264 if (feedback) { | 261 if (feedback) { |
265 count_crash_function_(); | 262 count_crash_function_(); |
266 | 263 |
267 if (!GetCreatedCrashDirectoryByEuid(kRootUid, | 264 if (!GetCreatedCrashDirectoryByEuid(kRootUid, |
268 &root_crash_directory, | 265 &root_crash_directory, |
269 NULL)) { | 266 NULL)) { |
270 return true; | 267 return true; |
271 } | 268 } |
272 | 269 |
273 std::string dump_basename = | 270 std::string dump_basename = |
274 FormatDumpBasename(kKernelExecName, | 271 FormatDumpBasename(kKernelExecName, |
275 time(NULL), | 272 time(NULL), |
276 kKernelPid); | 273 kKernelPid); |
277 FilePath kernel_crash_path = root_crash_directory.Append( | 274 FilePath kernel_crash_path = root_crash_directory.Append( |
278 StringPrintf("%s.kcrash", dump_basename.c_str())); | 275 StringPrintf("%s.kcrash", dump_basename.c_str())); |
279 | 276 |
280 // We must use WriteNewFile instead of file_util::WriteFile as we | 277 // We must use WriteNewFile instead of file_util::WriteFile as we |
281 // do not want to write with root access to a symlink that an attacker | 278 // do not want to write with root access to a symlink that an attacker |
282 // might have created. | 279 // might have created. |
283 if (WriteNewFile(kernel_crash_path, | 280 if (WriteNewFile(kernel_crash_path, |
284 kernel_dump.data(), | 281 kernel_dump.data(), |
285 kernel_dump.length()) != | 282 kernel_dump.length()) != |
286 static_cast<int>(kernel_dump.length())) { | 283 static_cast<int>(kernel_dump.length())) { |
287 logger_->LogInfo("Failed to write kernel dump to %s", | 284 LOG(INFO) << "Failed to write kernel dump to " |
288 kernel_crash_path.value().c_str()); | 285 << kernel_crash_path.value().c_str(); |
289 return true; | 286 return true; |
290 } | 287 } |
291 | 288 |
292 AddCrashMetaData(kKernelSignatureKey, signature); | 289 AddCrashMetaData(kKernelSignatureKey, signature); |
293 WriteCrashMetaData( | 290 WriteCrashMetaData( |
294 root_crash_directory.Append( | 291 root_crash_directory.Append( |
295 StringPrintf("%s.meta", dump_basename.c_str())), | 292 StringPrintf("%s.meta", dump_basename.c_str())), |
296 kKernelExecName, | 293 kKernelExecName, |
297 kernel_crash_path.value()); | 294 kernel_crash_path.value()); |
298 | 295 |
299 logger_->LogInfo("Stored kcrash to %s", | 296 LOG(INFO) << "Stored kcrash to " << kernel_crash_path.value(); |
300 kernel_crash_path.value().c_str()); | |
301 } | 297 } |
302 if (!ClearPreservedDump()) { | 298 if (!ClearPreservedDump()) { |
303 return false; | 299 return false; |
304 } | 300 } |
305 | 301 |
306 return true; | 302 return true; |
307 } | 303 } |
OLD | NEW |