linux: verify whether a broker has been successfully forked

Also fix an error in checking that PtraceClient was initialized.

Bug: crashpad:30
Change-Id: I1928340a2a642c2d831f0152bb9faaa12afb07e8
Reviewed-on: https://chromium-review.googlesource.com/978630
Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
Joshua Peraza 2018-03-23 12:26:44 -07:00
parent 9c89cd99f3
commit 6b23575b34
5 changed files with 35 additions and 15 deletions

View File

@ -63,7 +63,7 @@ bool CrashReportExceptionHandler::HandleExceptionWithBroker(
Metrics::ExceptionEncountered(); Metrics::ExceptionEncountered();
PtraceClient client; PtraceClient client;
if (client.Initialize(broker_sock, client_process_id)) { if (!client.Initialize(broker_sock, client_process_id)) {
Metrics::ExceptionCaptureResult( Metrics::ExceptionCaptureResult(
Metrics::CaptureResult::kBrokeredPtraceFailed); Metrics::CaptureResult::kBrokeredPtraceFailed);
return false; return false;

View File

@ -126,8 +126,10 @@ class PtraceStrategyDeciderImpl : public PtraceStrategyDecider {
Strategy ChooseStrategy(int sock, const ucred& client_credentials) override { Strategy ChooseStrategy(int sock, const ucred& client_credentials) override {
switch (GetPtraceScope()) { switch (GetPtraceScope()) {
case PtraceScope::kClassic: case PtraceScope::kClassic:
return getuid() == client_credentials.uid ? Strategy::kDirectPtrace if (getuid() == client_credentials.uid) {
: Strategy::kForkBroker; return Strategy::kDirectPtrace;
}
return TryForkingBroker(sock);
case PtraceScope::kRestricted: case PtraceScope::kRestricted:
if (!SendMessageToClient(sock, if (!SendMessageToClient(sock,
@ -143,7 +145,7 @@ class PtraceStrategyDeciderImpl : public PtraceStrategyDecider {
if (status != 0) { if (status != 0) {
errno = status; errno = status;
PLOG(ERROR) << "Handler Client SetPtracer"; PLOG(ERROR) << "Handler Client SetPtracer";
return Strategy::kForkBroker; return TryForkingBroker(sock);
} }
return Strategy::kDirectPtrace; return Strategy::kDirectPtrace;
@ -163,6 +165,26 @@ class PtraceStrategyDeciderImpl : public PtraceStrategyDecider {
DCHECK(false); DCHECK(false);
} }
private:
static Strategy TryForkingBroker(int client_sock) {
if (!SendMessageToClient(client_sock,
ServerToClientMessage::kTypeForkBroker)) {
return Strategy::kError;
}
Errno status;
if (!LoggingReadFileExactly(client_sock, &status, sizeof(status))) {
return Strategy::kError;
}
if (status != 0) {
errno = status;
PLOG(ERROR) << "Handler Client ForkBroker";
return Strategy::kNoPtrace;
}
return Strategy::kUseBroker;
}
}; };
} // namespace } // namespace
@ -427,12 +449,7 @@ bool ExceptionHandlerServer::HandleCrashDumpRequest(
client_info.exception_information_address); client_info.exception_information_address);
break; break;
case PtraceStrategyDecider::Strategy::kForkBroker: case PtraceStrategyDecider::Strategy::kUseBroker:
if (!SendMessageToClient(client_sock,
ServerToClientMessage::kTypeForkBroker)) {
return false;
}
delegate_->HandleExceptionWithBroker( delegate_->HandleExceptionWithBroker(
client_process_id, client_process_id,
client_info.exception_information_address, client_info.exception_information_address,

View File

@ -46,8 +46,8 @@ class PtraceStrategyDecider {
//! \brief The handler should `ptrace`-attach the client directly. //! \brief The handler should `ptrace`-attach the client directly.
kDirectPtrace, kDirectPtrace,
//! \brief The client should `fork` a PtraceBroker for the handler. //! \brief The client has `fork`ed a PtraceBroker for the handler.
kForkBroker, kUseBroker,
}; };
//! \brief Chooses an appropriate `ptrace` strategy. //! \brief Chooses an appropriate `ptrace` strategy.

View File

@ -289,7 +289,7 @@ TEST_F(ExceptionHandlerServerTest, RequestCrashDumpNoPtrace) {
} }
TEST_F(ExceptionHandlerServerTest, RequestCrashDumpForkBroker) { TEST_F(ExceptionHandlerServerTest, RequestCrashDumpForkBroker) {
ExpectCrashDumpUsingStrategy(PtraceStrategyDecider::Strategy::kForkBroker, ExpectCrashDumpUsingStrategy(PtraceStrategyDecider::Strategy::kUseBroker,
true); true);
} }

View File

@ -112,11 +112,14 @@ int ExceptionHandlerClient::WaitForCrashDumpComplete() {
Signals::InstallDefaultHandler(SIGCHLD); Signals::InstallDefaultHandler(SIGCHLD);
pid_t pid = fork(); pid_t pid = fork();
if (pid < 0) { if (pid <= 0) {
Errno error = errno; Errno error = pid < 0 ? errno : 0;
if (!WriteFile(server_sock_, &error, sizeof(error))) { if (!WriteFile(server_sock_, &error, sizeof(error))) {
return errno; return errno;
} }
}
if (pid < 0) {
continue; continue;
} }