blob: 7082569de37635111863665df1e62e370ceb4c9c [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
Ben Chan7e776902014-06-18 13:19:51 -07007#include <base/file_util.h>
8#include <base/logging.h>
9#include <base/strings/string_number_conversions.h>
10#include <base/strings/string_util.h>
11#include <base/strings/stringprintf.h>
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070012
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
Mike Frysingera557c112014-02-05 22:55:39 -050021using base::FilePath;
22using base::StringPrintf;
23
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070024KernelWarningCollector::KernelWarningCollector() {
25}
26
27KernelWarningCollector::~KernelWarningCollector() {
28}
29
30bool KernelWarningCollector::LoadKernelWarning(std::string *content,
Luigi Semenzatob20c9ef2013-12-17 18:12:09 -080031 std::string *signature) {
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070032 FilePath kernel_warning_path(kKernelWarningPath);
Mike Frysingera557c112014-02-05 22:55:39 -050033 if (!base::ReadFileToString(kernel_warning_path, content)) {
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070034 LOG(ERROR) << "Could not open " << kKernelWarningPath;
35 return false;
36 }
Ben Chan7e776902014-06-18 13:19:51 -070037 // The signature is in the first line.
Luigi Semenzatob20c9ef2013-12-17 18:12:09 -080038 std::string::size_type end_position = content->find('\n');
39 if (end_position == std::string::npos) {
40 LOG(ERROR) << "unexpected kernel warning format";
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070041 return false;
42 }
Luigi Semenzatob20c9ef2013-12-17 18:12:09 -080043 *signature = content->substr(0, end_position);
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070044 return true;
45}
46
47bool KernelWarningCollector::Collect() {
48 std::string reason = "normal collection";
49 bool feedback = true;
50 if (IsDeveloperImage()) {
51 reason = "always collect from developer builds";
52 feedback = true;
53 } else if (!is_feedback_allowed_function_()) {
54 reason = "no user consent";
55 feedback = false;
56 }
57
58 LOG(INFO) << "Processing kernel warning: " << reason;
59
60 if (!feedback) {
61 return true;
62 }
63
64 std::string kernel_warning;
Luigi Semenzatob20c9ef2013-12-17 18:12:09 -080065 std::string warning_signature;
66 if (!LoadKernelWarning(&kernel_warning, &warning_signature)) {
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070067 return true;
68 }
69
70 FilePath root_crash_directory;
71 if (!GetCreatedCrashDirectoryByEuid(kRootUid, &root_crash_directory, NULL)) {
72 return true;
73 }
74
75 std::string dump_basename =
76 FormatDumpBasename(kExecName, time(NULL), kKernelPid);
77 FilePath kernel_crash_path = root_crash_directory.Append(
78 StringPrintf("%s.kcrash", dump_basename.c_str()));
79
Ben Chanf30c6412014-05-22 23:09:01 -070080 // We must use WriteNewFile instead of base::WriteFile as we
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070081 // do not want to write with root access to a symlink that an attacker
82 // might have created.
83 if (WriteNewFile(kernel_crash_path,
84 kernel_warning.data(),
85 kernel_warning.length()) !=
86 static_cast<int>(kernel_warning.length())) {
87 LOG(INFO) << "Failed to write kernel warning to "
88 << kernel_crash_path.value().c_str();
89 return true;
90 }
91
Luigi Semenzatob20c9ef2013-12-17 18:12:09 -080092 AddCrashMetaData(kKernelWarningSignatureKey, warning_signature);
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070093 WriteCrashMetaData(
94 root_crash_directory.Append(
95 StringPrintf("%s.meta", dump_basename.c_str())),
96 kExecName, kernel_crash_path.value());
97
98 LOG(INFO) << "Stored kernel warning into " << kernel_crash_path.value();
99 return true;
100}