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 29 class SystemLogging; 30 31 // User crash collector. 32 class 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. Enable()53 bool Enable() { return SetUpInternal(true); } 54 55 // Disable collection. Disable()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