1 // Copyright 2017 The Crashpad Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef CRASHPAD_HANDLER_LINUX_EXCEPTION_HANDLER_SERVER_H_ 16 #define CRASHPAD_HANDLER_LINUX_EXCEPTION_HANDLER_SERVER_H_ 17 18 #include <stdint.h> 19 #include <sys/socket.h> 20 21 #include <atomic> 22 #include <memory> 23 #include <unordered_map> 24 25 #include "base/macros.h" 26 #include "util/file/file_io.h" 27 #include "util/linux/exception_handler_protocol.h" 28 #include "util/misc/address_types.h" 29 #include "util/misc/initialization_state_dcheck.h" 30 #include "util/misc/uuid.h" 31 32 namespace crashpad { 33 34 //! \brief Abstract base class for deciding how the handler should `ptrace` a 35 //! client. 36 class PtraceStrategyDecider { 37 public: 38 virtual ~PtraceStrategyDecider() = default; 39 40 //! \brief The possible return values for ChooseStrategy(). 41 enum class Strategy { 42 //! \brief An error occurred, with a message logged. 43 kError, 44 45 //! \brief Ptrace cannot be used. 46 kNoPtrace, 47 48 //! \brief The handler should `ptrace`-attach the client directly. 49 kDirectPtrace, 50 51 //! \brief The client has `fork`ed a PtraceBroker for the handler. 52 kUseBroker, 53 }; 54 55 //! \brief Chooses an appropriate `ptrace` strategy. 56 //! 57 //! \param[in] sock A socket conncted to a ExceptionHandlerClient. 58 //! \param[in] multiple_clients `true` if the socket is connected to multiple 59 //! clients. The broker is not supported in this configuration. 60 //! \param[in] client_credentials The credentials for the connected client. 61 //! \return the chosen #Strategy. 62 virtual Strategy ChooseStrategy(int sock, 63 bool multiple_clients, 64 const ucred& client_credentials) = 0; 65 66 protected: 67 PtraceStrategyDecider() = default; 68 }; 69 70 //! \brief Runs the main exception-handling server in Crashpad’s handler 71 //! process. 72 class ExceptionHandlerServer { 73 public: 74 class Delegate { 75 public: 76 //! \brief Called on receipt of a crash dump request from a client. 77 //! 78 //! \param[in] client_process_id The process ID of the crashing client. 79 //! \param[in] client_uid The user ID of the crashing client. 80 //! \param[in] info Information on the client. 81 //! \param[in] requesting_thread_stack_address Any address within the stack 82 //! range for the the thread that sent the crash dump request. Optional. 83 //! If unspecified or 0, \a requesting_thread_id will be -1. 84 //! \param[out] requesting_thread_id The thread ID of the thread which 85 //! requested the crash dump if not `nullptr`. Set to -1 if the thread 86 //! ID could not be determined. Optional. 87 //! \param[out] local_report_id The unique identifier for the report created 88 //! in the local report database. Optional. 89 //! \return `true` on success. `false` on failure with a message logged. 90 virtual bool HandleException( 91 pid_t client_process_id, 92 uid_t client_uid, 93 const ExceptionHandlerProtocol::ClientInformation& info, 94 VMAddress requesting_thread_stack_address = 0, 95 pid_t* requesting_thread_id = nullptr, 96 UUID* local_report_id = nullptr) = 0; 97 98 //! \brief Called on the receipt of a crash dump request from a client for a 99 //! crash that should be mediated by a PtraceBroker. 100 //! 101 //! \param[in] client_process_id The process ID of the crashing client. 102 //! \param[in] client_uid The uid of the crashing client. 103 //! \param[in] info Information on the client. 104 //! \param[in] broker_sock A socket connected to the PtraceBroker. 105 //! \param[out] local_report_id The unique identifier for the report created 106 //! in the local report database. Optional. 107 //! \return `true` on success. `false` on failure with a message logged. 108 virtual bool HandleExceptionWithBroker( 109 pid_t client_process_id, 110 uid_t client_uid, 111 const ExceptionHandlerProtocol::ClientInformation& info, 112 int broker_sock, 113 UUID* local_report_id = nullptr) = 0; 114 ~Delegate()115 virtual ~Delegate() {} 116 }; 117 118 ExceptionHandlerServer(); 119 ~ExceptionHandlerServer(); 120 121 //! \brief Sets the handler's PtraceStrategyDecider. 122 //! 123 //! If this method is not called, a default PtraceStrategyDecider will be 124 //! used. 125 void SetPtraceStrategyDecider(std::unique_ptr<PtraceStrategyDecider> decider); 126 127 //! \brief Initializes this object. 128 //! 129 //! This method must be successfully called before Run(). 130 //! 131 //! \param[in] sock A socket on which to receive client requests. 132 //! \param[in] multiple_clients `true` if this socket is used by multiple 133 //! clients. Using a broker process is not supported in this 134 //! configuration. 135 //! \return `true` on success. `false` on failure with a message logged. 136 bool InitializeWithClient(ScopedFileHandle sock, bool multiple_clients); 137 138 //! \brief Runs the exception-handling server. 139 //! 140 //! This method must only be called once on an ExceptionHandlerServer object. 141 //! This method returns when there are no more client connections or Stop() 142 //! has been called. 143 //! 144 //! \param[in] delegate An object to send exceptions to. 145 void Run(Delegate* delegate); 146 147 //! \brief Stops a running exception-handling server. 148 //! 149 //! Stop() may be called at any time, and may be called from a signal handler. 150 //! If Stop() is called before Run() it will cause Run() to return as soon as 151 //! it is called. It is harmless to call Stop() after Run() has already 152 //! returned, or to call Stop() after it has already been called. 153 void Stop(); 154 155 private: 156 struct Event { 157 enum class Type { 158 // Used by Stop() to shutdown the server. 159 kShutdown, 160 161 // A message from a client on a private socket connection. 162 kClientMessage, 163 164 // A message from a client on a shared socket connection. 165 kSharedSocketMessage 166 }; 167 168 Type type; 169 ScopedFileHandle fd; 170 }; 171 172 void HandleEvent(Event* event, uint32_t event_type); 173 bool InstallClientSocket(ScopedFileHandle socket, Event::Type type); 174 bool UninstallClientSocket(Event* event); 175 bool ReceiveClientMessage(Event* event); 176 bool HandleCrashDumpRequest( 177 const ucred& creds, 178 const ExceptionHandlerProtocol::ClientInformation& client_info, 179 VMAddress requesting_thread_stack_address, 180 int client_sock, 181 bool multiple_clients); 182 183 std::unordered_map<int, std::unique_ptr<Event>> clients_; 184 std::unique_ptr<Event> shutdown_event_; 185 std::unique_ptr<PtraceStrategyDecider> strategy_decider_; 186 Delegate* delegate_; 187 ScopedFileHandle pollfd_; 188 std::atomic<bool> keep_running_; 189 InitializationStateDcheck initialized_; 190 191 DISALLOW_COPY_AND_ASSIGN(ExceptionHandlerServer); 192 }; 193 194 } // namespace crashpad 195 196 #endif // CRASHPAD_HANDLER_LINUX_EXCEPTION_HANDLER_SERVER_H_ 197