blob: b504f497b06b02b94a0d39704bcc0e4b3220bf05 [file] [log] [blame]
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "crash-reporter/kernel_warning_collector.h"
6
7#include "base/file_util.h"
8#include "base/logging.h"
9#include "base/string_number_conversions.h"
10#include "base/string_util.h"
11#include "base/stringprintf.h"
12
13namespace {
14const char kExecName[] = "kernel-warning";
15const char kKernelWarningSignatureKey[] = "sig";
16const char kKernelWarningPath[] = "/var/run/kwarn/warning";
17const pid_t kKernelPid = 0;
18const uid_t kRootUid = 0;
19} // namespace
20
21KernelWarningCollector::KernelWarningCollector() {
22}
23
24KernelWarningCollector::~KernelWarningCollector() {
25}
26
27bool KernelWarningCollector::LoadKernelWarning(std::string *content,
28 std::string *hash_string) {
29 FilePath kernel_warning_path(kKernelWarningPath);
30 if (!file_util::ReadFileToString(kernel_warning_path, content)) {
31 LOG(ERROR) << "Could not open " << kKernelWarningPath;
32 return false;
33 }
34 /* Verify that the first line contains an 8-digit hex hash. */
35 *hash_string = content->substr(0, 8);
36 std::vector<uint8> output;
37 if (!base::HexStringToBytes(*hash_string, &output)) {
38 LOG(ERROR) << "Bad hash " << *hash_string << " in " << kKernelWarningPath;
39 return false;
40 }
41 return true;
42}
43
44bool KernelWarningCollector::Collect() {
45 std::string reason = "normal collection";
46 bool feedback = true;
47 if (IsDeveloperImage()) {
48 reason = "always collect from developer builds";
49 feedback = true;
50 } else if (!is_feedback_allowed_function_()) {
51 reason = "no user consent";
52 feedback = false;
53 }
54
55 LOG(INFO) << "Processing kernel warning: " << reason;
56
57 if (!feedback) {
58 return true;
59 }
60
61 std::string kernel_warning;
62 std::string warning_hash;
63 if (!LoadKernelWarning(&kernel_warning, &warning_hash)) {
64 return true;
65 }
66
67 FilePath root_crash_directory;
68 if (!GetCreatedCrashDirectoryByEuid(kRootUid, &root_crash_directory, NULL)) {
69 return true;
70 }
71
72 std::string dump_basename =
73 FormatDumpBasename(kExecName, time(NULL), kKernelPid);
74 FilePath kernel_crash_path = root_crash_directory.Append(
75 StringPrintf("%s.kcrash", dump_basename.c_str()));
76
77 // We must use WriteNewFile instead of file_util::WriteFile as we
78 // do not want to write with root access to a symlink that an attacker
79 // might have created.
80 if (WriteNewFile(kernel_crash_path,
81 kernel_warning.data(),
82 kernel_warning.length()) !=
83 static_cast<int>(kernel_warning.length())) {
84 LOG(INFO) << "Failed to write kernel warning to "
85 << kernel_crash_path.value().c_str();
86 return true;
87 }
88
89 AddCrashMetaData(kKernelWarningSignatureKey, warning_hash);
90 WriteCrashMetaData(
91 root_crash_directory.Append(
92 StringPrintf("%s.meta", dump_basename.c_str())),
93 kExecName, kernel_crash_path.value());
94
95 LOG(INFO) << "Stored kernel warning into " << kernel_crash_path.value();
96 return true;
97}