blob: 5dcd1f688394ec677409e078f9b0b3b33bfc1f9a [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 Chanab6cc902014-09-05 08:21:06 -07007#include <base/files/file_util.h>
Ben Chan7e776902014-06-18 13:19:51 -07008#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;
Ben Chan262d7982014-09-18 08:05:20 -070071 if (!GetCreatedCrashDirectoryByEuid(kRootUid, &root_crash_directory,
72 nullptr)) {
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070073 return true;
74 }
75
76 std::string dump_basename =
Ben Chan262d7982014-09-18 08:05:20 -070077 FormatDumpBasename(kExecName, time(nullptr), kKernelPid);
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070078 FilePath kernel_crash_path = root_crash_directory.Append(
79 StringPrintf("%s.kcrash", dump_basename.c_str()));
80
Ben Chanf30c6412014-05-22 23:09:01 -070081 // We must use WriteNewFile instead of base::WriteFile as we
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070082 // do not want to write with root access to a symlink that an attacker
83 // might have created.
84 if (WriteNewFile(kernel_crash_path,
85 kernel_warning.data(),
86 kernel_warning.length()) !=
87 static_cast<int>(kernel_warning.length())) {
88 LOG(INFO) << "Failed to write kernel warning to "
89 << kernel_crash_path.value().c_str();
90 return true;
91 }
92
Luigi Semenzatob20c9ef2013-12-17 18:12:09 -080093 AddCrashMetaData(kKernelWarningSignatureKey, warning_signature);
Luigi Semenzato6fdc0b42013-04-11 17:22:13 -070094 WriteCrashMetaData(
95 root_crash_directory.Append(
96 StringPrintf("%s.meta", dump_basename.c_str())),
97 kExecName, kernel_crash_path.value());
98
99 LOG(INFO) << "Stored kernel warning into " << kernel_crash_path.value();
100 return true;
101}