Home | History | Annotate | Download | only in crash_reporter
      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.
     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