| Index: third_party/crashpad/crashpad/util/win/exception_handler_server.cc
|
| diff --git a/third_party/crashpad/crashpad/util/win/exception_handler_server.cc b/third_party/crashpad/crashpad/util/win/exception_handler_server.cc
|
| index 39575dffad8f04ab813268df5152f4a65c2a9d19..70955c825b73afa1e56840fa0d23231d055f5519 100644
|
| --- a/third_party/crashpad/crashpad/util/win/exception_handler_server.cc
|
| +++ b/third_party/crashpad/crashpad/util/win/exception_handler_server.cc
|
| @@ -14,7 +14,6 @@
|
|
|
| #include "util/win/exception_handler_server.h"
|
|
|
| -#include <sddl.h>
|
| #include <stdint.h>
|
| #include <string.h>
|
| #include <sys/types.h>
|
| @@ -30,73 +29,17 @@
|
| #include "snapshot/crashpad_info_client_options.h"
|
| #include "snapshot/win/process_snapshot_win.h"
|
| #include "util/file/file_writer.h"
|
| -#include "util/misc/random_string.h"
|
| #include "util/misc/tri_state.h"
|
| #include "util/misc/uuid.h"
|
| #include "util/win/get_function.h"
|
| #include "util/win/handle.h"
|
| #include "util/win/registration_protocol_win.h"
|
| -#include "util/win/scoped_local_alloc.h"
|
| #include "util/win/xp_compat.h"
|
|
|
| namespace crashpad {
|
|
|
| namespace {
|
|
|
| -// We create two pipe instances, so that there's one listening while the
|
| -// PipeServiceProc is processing a registration.
|
| -const size_t kPipeInstances = 2;
|
| -
|
| -// Wraps CreateNamedPipe() to create a single named pipe instance.
|
| -//
|
| -// If first_instance is true, the named pipe instance will be created with
|
| -// FILE_FLAG_FIRST_PIPE_INSTANCE. This ensures that the the pipe name is not
|
| -// already in use when created. The first instance will be created with an
|
| -// untrusted integrity SACL so instances of this pipe can be connected to by
|
| -// processes of any integrity level.
|
| -HANDLE CreateNamedPipeInstance(const std::wstring& pipe_name,
|
| - bool first_instance) {
|
| - SECURITY_ATTRIBUTES security_attributes;
|
| - SECURITY_ATTRIBUTES* security_attributes_pointer = nullptr;
|
| - ScopedLocalAlloc scoped_sec_desc;
|
| -
|
| - if (first_instance) {
|
| - // Pre-Vista does not have integrity levels.
|
| - const DWORD version = GetVersion();
|
| - const DWORD major_version = LOBYTE(LOWORD(version));
|
| - const bool is_vista_or_later = major_version >= 6;
|
| - if (is_vista_or_later) {
|
| - // Mandatory Label, no ACE flags, no ObjectType, integrity level
|
| - // untrusted.
|
| - const wchar_t kSddl[] = L"S:(ML;;;;;S-1-16-0)";
|
| -
|
| - PSECURITY_DESCRIPTOR sec_desc;
|
| - PCHECK(ConvertStringSecurityDescriptorToSecurityDescriptor(
|
| - kSddl, SDDL_REVISION_1, &sec_desc, nullptr))
|
| - << "ConvertStringSecurityDescriptorToSecurityDescriptor";
|
| -
|
| - // Take ownership of the allocated SECURITY_DESCRIPTOR.
|
| - scoped_sec_desc.reset(sec_desc);
|
| -
|
| - memset(&security_attributes, 0, sizeof(security_attributes));
|
| - security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
|
| - security_attributes.lpSecurityDescriptor = sec_desc;
|
| - security_attributes.bInheritHandle = FALSE;
|
| - security_attributes_pointer = &security_attributes;
|
| - }
|
| - }
|
| -
|
| - return CreateNamedPipe(
|
| - pipe_name.c_str(),
|
| - PIPE_ACCESS_DUPLEX | (first_instance ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0),
|
| - PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
| - kPipeInstances,
|
| - 512,
|
| - 512,
|
| - 0,
|
| - security_attributes_pointer);
|
| -}
|
| -
|
| decltype(GetNamedPipeClientProcessId)* GetNamedPipeClientProcessIdFunction() {
|
| static const auto get_named_pipe_client_process_id =
|
| GET_FUNCTION(L"kernel32.dll", ::GetNamedPipeClientProcessId);
|
| @@ -165,6 +108,9 @@ class ClientData {
|
| ClientData(HANDLE port,
|
| ExceptionHandlerServer::Delegate* delegate,
|
| ScopedKernelHANDLE process,
|
| + ScopedKernelHANDLE crash_dump_requested_event,
|
| + ScopedKernelHANDLE non_crash_dump_requested_event,
|
| + ScopedKernelHANDLE non_crash_dump_completed_event,
|
| WinVMAddress crash_exception_information_address,
|
| WinVMAddress non_crash_exception_information_address,
|
| WinVMAddress debug_critical_section_address,
|
| @@ -177,12 +123,11 @@ class ClientData {
|
| lock_(),
|
| port_(port),
|
| delegate_(delegate),
|
| - crash_dump_requested_event_(
|
| - CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
|
| + crash_dump_requested_event_(std::move(crash_dump_requested_event)),
|
| non_crash_dump_requested_event_(
|
| - CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
|
| + std::move(non_crash_dump_requested_event)),
|
| non_crash_dump_completed_event_(
|
| - CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
|
| + std::move(non_crash_dump_completed_event)),
|
| process_(std::move(process)),
|
| crash_exception_information_address_(
|
| crash_exception_information_address),
|
| @@ -315,36 +260,47 @@ void ExceptionHandlerServer::SetPipeName(const std::wstring& pipe_name) {
|
| pipe_name_ = pipe_name;
|
| }
|
|
|
| -std::wstring ExceptionHandlerServer::CreatePipe() {
|
| +void ExceptionHandlerServer::InitializeWithInheritedDataForInitialClient(
|
| + const InitialClientData& initial_client_data,
|
| + Delegate* delegate) {
|
| + DCHECK(pipe_name_.empty());
|
| DCHECK(!first_pipe_instance_.is_valid());
|
|
|
| - int tries = 5;
|
| - std::string pipe_name_base =
|
| - base::StringPrintf("\\\\.\\pipe\\crashpad_%d_", GetCurrentProcessId());
|
| - std::wstring pipe_name;
|
| - do {
|
| - pipe_name = base::UTF8ToUTF16(pipe_name_base + RandomString());
|
| -
|
| - first_pipe_instance_.reset(CreateNamedPipeInstance(pipe_name, true));
|
| -
|
| - // CreateNamedPipe() is documented as setting the error to
|
| - // ERROR_ACCESS_DENIED if FILE_FLAG_FIRST_PIPE_INSTANCE is specified and the
|
| - // pipe name is already in use. However it may set the error to other codes
|
| - // such as ERROR_PIPE_BUSY (if the pipe already exists and has reached its
|
| - // maximum instance count) or ERROR_INVALID_PARAMETER (if the pipe already
|
| - // exists and its attributes differ from those specified to
|
| - // CreateNamedPipe()). Some of these errors may be ambiguous: for example,
|
| - // ERROR_INVALID_PARAMETER may also occur if CreateNamedPipe() is called
|
| - // incorrectly even in the absence of an existing pipe by the same name.
|
| - //
|
| - // Rather than chasing down all of the possible errors that might indicate
|
| - // that a pipe name is already in use, retry up to a few times on any error.
|
| - } while (!first_pipe_instance_.is_valid() && --tries);
|
| -
|
| - PCHECK(first_pipe_instance_.is_valid()) << "CreateNamedPipe";
|
| -
|
| - SetPipeName(pipe_name);
|
| - return pipe_name;
|
| + first_pipe_instance_.reset(initial_client_data.first_pipe_instance());
|
| +
|
| + // TODO(scottmg): Vista+. Might need to pass through or possibly find an Nt*.
|
| + size_t bytes = sizeof(wchar_t) * _MAX_PATH + sizeof(FILE_NAME_INFO);
|
| + std::unique_ptr<uint8_t[]> data(new uint8_t[bytes]);
|
| + if (!GetFileInformationByHandleEx(first_pipe_instance_.get(),
|
| + FileNameInfo,
|
| + data.get(),
|
| + static_cast<DWORD>(bytes))) {
|
| + PLOG(FATAL) << "GetFileInformationByHandleEx";
|
| + }
|
| + FILE_NAME_INFO* file_name_info =
|
| + reinterpret_cast<FILE_NAME_INFO*>(data.get());
|
| + pipe_name_ =
|
| + L"\\\\.\\pipe" + std::wstring(file_name_info->FileName,
|
| + file_name_info->FileNameLength /
|
| + sizeof(file_name_info->FileName[0]));
|
| +
|
| + {
|
| + base::AutoLock lock(clients_lock_);
|
| + internal::ClientData* client = new internal::ClientData(
|
| + port_.get(),
|
| + delegate,
|
| + ScopedKernelHANDLE(initial_client_data.client_process()),
|
| + ScopedKernelHANDLE(initial_client_data.request_crash_dump()),
|
| + ScopedKernelHANDLE(initial_client_data.request_non_crash_dump()),
|
| + ScopedKernelHANDLE(initial_client_data.non_crash_dump_completed()),
|
| + initial_client_data.crash_exception_information(),
|
| + initial_client_data.non_crash_exception_information(),
|
| + initial_client_data.debug_critical_section_address(),
|
| + &OnCrashDumpEvent,
|
| + &OnNonCrashDumpEvent,
|
| + &OnProcessEnd);
|
| + clients_.insert(client);
|
| + }
|
| }
|
|
|
| void ExceptionHandlerServer::Run(Delegate* delegate) {
|
| @@ -457,6 +413,16 @@ bool ExceptionHandlerServer::ServiceClientConnection(
|
| return true;
|
| }
|
|
|
| + case ClientToServerMessage::kPing: {
|
| + // No action required, the fact that the message was processed is
|
| + // sufficient.
|
| + ServerToClientMessage shutdown_response = {};
|
| + LoggingWriteFile(service_context.pipe(),
|
| + &shutdown_response,
|
| + sizeof(shutdown_response));
|
| + return false;
|
| + }
|
| +
|
| case ClientToServerMessage::kRegister:
|
| // Handled below.
|
| break;
|
| @@ -513,6 +479,12 @@ bool ExceptionHandlerServer::ServiceClientConnection(
|
| service_context.port(),
|
| service_context.delegate(),
|
| ScopedKernelHANDLE(client_process),
|
| + ScopedKernelHANDLE(
|
| + CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
|
| + ScopedKernelHANDLE(
|
| + CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
|
| + ScopedKernelHANDLE(
|
| + CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
|
| message.registration.crash_exception_information,
|
| message.registration.non_crash_exception_information,
|
| message.registration.critical_section_address,
|
|
|