1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef CRASH_REPORTER_USER_COLLECTOR_H_
18#define CRASH_REPORTER_USER_COLLECTOR_H_
19
20#include <string>
21#include <vector>
22
23#include <base/files/file_path.h>
24#include <base/macros.h>
25#include <gtest/gtest_prod.h>  // for FRIEND_TEST
26
27#include "crash_collector.h"
28
29class SystemLogging;
30
31// User crash collector.
32class UserCollector : public CrashCollector {
33 public:
34  UserCollector();
35
36  // Initialize the user crash collector for detection of crashes,
37  // given a crash counting function, the path to this executable,
38  // metrics collection enabled oracle, and system logger facility.
39  // Crash detection/reporting is not enabled until Enable is called.
40  // |generate_diagnostics| is used to indicate whether or not to try
41  // to generate a minidump from crashes.
42  void Initialize(CountCrashFunction count_crash,
43                  const std::string &our_path,
44                  IsFeedbackAllowedFunction is_metrics_allowed,
45                  bool generate_diagnostics,
46                  bool core2md_failure,
47                  bool directory_failure,
48                  const std::string &filter_in);
49
50  ~UserCollector() override;
51
52  // Enable collection.
53  bool Enable() { return SetUpInternal(true); }
54
55  // Disable collection.
56  bool Disable() { return SetUpInternal(false); }
57
58  // Handle a specific user crash.  Returns true on success.
59  bool HandleCrash(const std::string &crash_attributes,
60                   const char *force_exec);
61
62 private:
63  friend class UserCollectorTest;
64  FRIEND_TEST(UserCollectorTest, CopyOffProcFilesBadPath);
65  FRIEND_TEST(UserCollectorTest, CopyOffProcFilesBadPid);
66  FRIEND_TEST(UserCollectorTest, CopyOffProcFilesOK);
67  FRIEND_TEST(UserCollectorTest, GetExecutableBaseNameFromPid);
68  FRIEND_TEST(UserCollectorTest, GetFirstLineWithPrefix);
69  FRIEND_TEST(UserCollectorTest, GetIdFromStatus);
70  FRIEND_TEST(UserCollectorTest, GetStateFromStatus);
71  FRIEND_TEST(UserCollectorTest, GetProcessPath);
72  FRIEND_TEST(UserCollectorTest, GetSymlinkTarget);
73  FRIEND_TEST(UserCollectorTest, GetUserInfoFromName);
74  FRIEND_TEST(UserCollectorTest, ParseCrashAttributes);
75  FRIEND_TEST(UserCollectorTest, ShouldDumpChromeOverridesDeveloperImage);
76  FRIEND_TEST(UserCollectorTest, ShouldDumpDeveloperImageOverridesConsent);
77  FRIEND_TEST(UserCollectorTest, ShouldDumpUseConsentProductionImage);
78  FRIEND_TEST(UserCollectorTest, ValidateProcFiles);
79  FRIEND_TEST(UserCollectorTest, ValidateCoreFile);
80
81  // Enumeration to pass to GetIdFromStatus.  Must match the order
82  // that the kernel lists IDs in the status file.
83  enum IdKind {
84    kIdReal = 0,  // uid and gid
85    kIdEffective = 1,  // euid and egid
86    kIdSet = 2,  // suid and sgid
87    kIdFileSystem = 3,  // fsuid and fsgid
88    kIdMax
89  };
90
91  enum ErrorType {
92    kErrorNone,
93    kErrorSystemIssue,
94    kErrorReadCoreData,
95    kErrorUnusableProcFiles,
96    kErrorInvalidCoreFile,
97    kErrorUnsupported32BitCoreFile,
98    kErrorCore2MinidumpConversion,
99  };
100
101  static const int kForkProblem = 255;
102
103  // Returns an error type signature for a given |error_type| value,
104  // which is reported to the crash server along with the
105  // crash_reporter-user-collection signature.
106  std::string GetErrorTypeSignature(ErrorType error_type) const;
107
108  bool SetUpInternal(bool enabled);
109
110  // Returns, via |line|, the first line in |lines| that starts with |prefix|.
111  // Returns true if a line is found, or false otherwise.
112  bool GetFirstLineWithPrefix(const std::vector<std::string> &lines,
113                              const char *prefix, std::string *line);
114
115  // Returns the identifier of |kind|, via |id|, found in |status_lines| on
116  // the line starting with |prefix|. |status_lines| contains the lines in
117  // the status file. Returns true if the identifier can be determined.
118  bool GetIdFromStatus(const char *prefix,
119                       IdKind kind,
120                       const std::vector<std::string> &status_lines,
121                       int *id);
122
123  // Returns the process state, via |state|, found in |status_lines|, which
124  // contains the lines in the status file. Returns true if the process state
125  // can be determined.
126  bool GetStateFromStatus(const std::vector<std::string> &status_lines,
127                          std::string *state);
128
129  void LogCollectionError(const std::string &error_message);
130  void EnqueueCollectionErrorLog(pid_t pid, ErrorType error_type,
131                                 const std::string &exec_name);
132
133  bool CopyOffProcFiles(pid_t pid, const base::FilePath &container_dir);
134
135  // Validates the proc files at |container_dir| and returns true if they
136  // are usable for the core-to-minidump conversion later. For instance, if
137  // a process is reaped by the kernel before the copying of its proc files
138  // takes place, some proc files like /proc/<pid>/maps may contain nothing
139  // and thus become unusable.
140  bool ValidateProcFiles(const base::FilePath &container_dir) const;
141
142  // Validates the core file at |core_path| and returns kErrorNone if
143  // the file contains the ELF magic bytes and an ELF class that matches the
144  // platform (i.e. 32-bit ELF on a 32-bit platform or 64-bit ELF on a 64-bit
145  // platform), which is due to the limitation in core2md. It returns an error
146  // type otherwise.
147  ErrorType ValidateCoreFile(const base::FilePath &core_path) const;
148
149  // Determines the crash directory for given pid based on pid's owner,
150  // and creates the directory if necessary with appropriate permissions.
151  // Returns true whether or not directory needed to be created, false on
152  // any failure.
153  bool GetCreatedCrashDirectory(pid_t pid, uid_t supplied_ruid,
154                                base::FilePath *crash_file_path,
155                                bool *out_of_capacity);
156  bool CopyStdinToCoreFile(const base::FilePath &core_path);
157  bool RunCoreToMinidump(const base::FilePath &core_path,
158                         const base::FilePath &procfs_directory,
159                         const base::FilePath &minidump_path,
160                         const base::FilePath &temp_directory);
161  ErrorType ConvertCoreToMinidump(pid_t pid,
162                                  const base::FilePath &container_dir,
163                                  const base::FilePath &core_path,
164                                  const base::FilePath &minidump_path);
165  ErrorType ConvertAndEnqueueCrash(pid_t pid, const std::string &exec_name,
166                                   uid_t supplied_ruid, bool *out_of_capacity);
167  bool ParseCrashAttributes(const std::string &crash_attributes,
168                            pid_t *pid, int *signal, uid_t *uid, gid_t *gid,
169                            std::string *kernel_supplied_name);
170
171  bool ShouldDump(bool has_owner_consent,
172                  bool is_developer,
173                  std::string *reason);
174
175  bool generate_diagnostics_;
176  std::string our_path_;
177  bool initialized_;
178
179  bool core2md_failure_;
180  bool directory_failure_;
181  std::string filter_in_;
182
183  static const char *kUserId;
184  static const char *kGroupId;
185
186  DISALLOW_COPY_AND_ASSIGN(UserCollector);
187};
188
189#endif  // CRASH_REPORTER_USER_COLLECTOR_H_
190