Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(626)

Side by Side Diff: third_party/crashpad/crashpad/util/win/exception_handler_server.cc

Issue 2478633002: Update Crashpad to b47bf6c250c6b825dee1c5fbad9152c2c962e828 (Closed)
Patch Set: mac comment 2 Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Crashpad Authors. All rights reserved. 1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with 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 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 14
15 #include "util/win/exception_handler_server.h" 15 #include "util/win/exception_handler_server.h"
16 16
17 #include <sddl.h>
18 #include <stdint.h> 17 #include <stdint.h>
19 #include <string.h> 18 #include <string.h>
20 #include <sys/types.h> 19 #include <sys/types.h>
21 20
22 #include <utility> 21 #include <utility>
23 22
24 #include "base/logging.h" 23 #include "base/logging.h"
25 #include "base/numerics/safe_conversions.h" 24 #include "base/numerics/safe_conversions.h"
26 #include "base/rand_util.h" 25 #include "base/rand_util.h"
27 #include "base/strings/stringprintf.h" 26 #include "base/strings/stringprintf.h"
28 #include "base/strings/utf_string_conversions.h" 27 #include "base/strings/utf_string_conversions.h"
29 #include "minidump/minidump_file_writer.h" 28 #include "minidump/minidump_file_writer.h"
30 #include "snapshot/crashpad_info_client_options.h" 29 #include "snapshot/crashpad_info_client_options.h"
31 #include "snapshot/win/process_snapshot_win.h" 30 #include "snapshot/win/process_snapshot_win.h"
32 #include "util/file/file_writer.h" 31 #include "util/file/file_writer.h"
33 #include "util/misc/random_string.h"
34 #include "util/misc/tri_state.h" 32 #include "util/misc/tri_state.h"
35 #include "util/misc/uuid.h" 33 #include "util/misc/uuid.h"
36 #include "util/win/get_function.h" 34 #include "util/win/get_function.h"
37 #include "util/win/handle.h" 35 #include "util/win/handle.h"
38 #include "util/win/registration_protocol_win.h" 36 #include "util/win/registration_protocol_win.h"
39 #include "util/win/scoped_local_alloc.h"
40 #include "util/win/xp_compat.h" 37 #include "util/win/xp_compat.h"
41 38
42 namespace crashpad { 39 namespace crashpad {
43 40
44 namespace { 41 namespace {
45 42
46 // We create two pipe instances, so that there's one listening while the
47 // PipeServiceProc is processing a registration.
48 const size_t kPipeInstances = 2;
49
50 // Wraps CreateNamedPipe() to create a single named pipe instance.
51 //
52 // If first_instance is true, the named pipe instance will be created with
53 // FILE_FLAG_FIRST_PIPE_INSTANCE. This ensures that the the pipe name is not
54 // already in use when created. The first instance will be created with an
55 // untrusted integrity SACL so instances of this pipe can be connected to by
56 // processes of any integrity level.
57 HANDLE CreateNamedPipeInstance(const std::wstring& pipe_name,
58 bool first_instance) {
59 SECURITY_ATTRIBUTES security_attributes;
60 SECURITY_ATTRIBUTES* security_attributes_pointer = nullptr;
61 ScopedLocalAlloc scoped_sec_desc;
62
63 if (first_instance) {
64 // Pre-Vista does not have integrity levels.
65 const DWORD version = GetVersion();
66 const DWORD major_version = LOBYTE(LOWORD(version));
67 const bool is_vista_or_later = major_version >= 6;
68 if (is_vista_or_later) {
69 // Mandatory Label, no ACE flags, no ObjectType, integrity level
70 // untrusted.
71 const wchar_t kSddl[] = L"S:(ML;;;;;S-1-16-0)";
72
73 PSECURITY_DESCRIPTOR sec_desc;
74 PCHECK(ConvertStringSecurityDescriptorToSecurityDescriptor(
75 kSddl, SDDL_REVISION_1, &sec_desc, nullptr))
76 << "ConvertStringSecurityDescriptorToSecurityDescriptor";
77
78 // Take ownership of the allocated SECURITY_DESCRIPTOR.
79 scoped_sec_desc.reset(sec_desc);
80
81 memset(&security_attributes, 0, sizeof(security_attributes));
82 security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
83 security_attributes.lpSecurityDescriptor = sec_desc;
84 security_attributes.bInheritHandle = FALSE;
85 security_attributes_pointer = &security_attributes;
86 }
87 }
88
89 return CreateNamedPipe(
90 pipe_name.c_str(),
91 PIPE_ACCESS_DUPLEX | (first_instance ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0),
92 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
93 kPipeInstances,
94 512,
95 512,
96 0,
97 security_attributes_pointer);
98 }
99
100 decltype(GetNamedPipeClientProcessId)* GetNamedPipeClientProcessIdFunction() { 43 decltype(GetNamedPipeClientProcessId)* GetNamedPipeClientProcessIdFunction() {
101 static const auto get_named_pipe_client_process_id = 44 static const auto get_named_pipe_client_process_id =
102 GET_FUNCTION(L"kernel32.dll", ::GetNamedPipeClientProcessId); 45 GET_FUNCTION(L"kernel32.dll", ::GetNamedPipeClientProcessId);
103 return get_named_pipe_client_process_id; 46 return get_named_pipe_client_process_id;
104 } 47 }
105 48
106 HANDLE DuplicateEvent(HANDLE process, HANDLE event) { 49 HANDLE DuplicateEvent(HANDLE process, HANDLE event) {
107 HANDLE handle; 50 HANDLE handle;
108 if (DuplicateHandle(GetCurrentProcess(), 51 if (DuplicateHandle(GetCurrentProcess(),
109 event, 52 event,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 //! \brief The context data for registered threadpool waits. 101 //! \brief The context data for registered threadpool waits.
159 //! 102 //!
160 //! This object must be created and destroyed on the main thread. Access must be 103 //! This object must be created and destroyed on the main thread. Access must be
161 //! guarded by use of the lock() with the exception of the threadpool wait 104 //! guarded by use of the lock() with the exception of the threadpool wait
162 //! variables which are accessed only by the main thread. 105 //! variables which are accessed only by the main thread.
163 class ClientData { 106 class ClientData {
164 public: 107 public:
165 ClientData(HANDLE port, 108 ClientData(HANDLE port,
166 ExceptionHandlerServer::Delegate* delegate, 109 ExceptionHandlerServer::Delegate* delegate,
167 ScopedKernelHANDLE process, 110 ScopedKernelHANDLE process,
111 ScopedKernelHANDLE crash_dump_requested_event,
112 ScopedKernelHANDLE non_crash_dump_requested_event,
113 ScopedKernelHANDLE non_crash_dump_completed_event,
168 WinVMAddress crash_exception_information_address, 114 WinVMAddress crash_exception_information_address,
169 WinVMAddress non_crash_exception_information_address, 115 WinVMAddress non_crash_exception_information_address,
170 WinVMAddress debug_critical_section_address, 116 WinVMAddress debug_critical_section_address,
171 WAITORTIMERCALLBACK crash_dump_request_callback, 117 WAITORTIMERCALLBACK crash_dump_request_callback,
172 WAITORTIMERCALLBACK non_crash_dump_request_callback, 118 WAITORTIMERCALLBACK non_crash_dump_request_callback,
173 WAITORTIMERCALLBACK process_end_callback) 119 WAITORTIMERCALLBACK process_end_callback)
174 : crash_dump_request_thread_pool_wait_(INVALID_HANDLE_VALUE), 120 : crash_dump_request_thread_pool_wait_(INVALID_HANDLE_VALUE),
175 non_crash_dump_request_thread_pool_wait_(INVALID_HANDLE_VALUE), 121 non_crash_dump_request_thread_pool_wait_(INVALID_HANDLE_VALUE),
176 process_end_thread_pool_wait_(INVALID_HANDLE_VALUE), 122 process_end_thread_pool_wait_(INVALID_HANDLE_VALUE),
177 lock_(), 123 lock_(),
178 port_(port), 124 port_(port),
179 delegate_(delegate), 125 delegate_(delegate),
180 crash_dump_requested_event_( 126 crash_dump_requested_event_(std::move(crash_dump_requested_event)),
181 CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
182 non_crash_dump_requested_event_( 127 non_crash_dump_requested_event_(
183 CreateEvent(nullptr, false /* auto reset */, false, nullptr)), 128 std::move(non_crash_dump_requested_event)),
184 non_crash_dump_completed_event_( 129 non_crash_dump_completed_event_(
185 CreateEvent(nullptr, false /* auto reset */, false, nullptr)), 130 std::move(non_crash_dump_completed_event)),
186 process_(std::move(process)), 131 process_(std::move(process)),
187 crash_exception_information_address_( 132 crash_exception_information_address_(
188 crash_exception_information_address), 133 crash_exception_information_address),
189 non_crash_exception_information_address_( 134 non_crash_exception_information_address_(
190 non_crash_exception_information_address), 135 non_crash_exception_information_address),
191 debug_critical_section_address_(debug_critical_section_address) { 136 debug_critical_section_address_(debug_critical_section_address) {
192 RegisterThreadPoolWaits(crash_dump_request_callback, 137 RegisterThreadPoolWaits(crash_dump_request_callback,
193 non_crash_dump_request_callback, 138 non_crash_dump_request_callback,
194 process_end_callback); 139 process_end_callback);
195 } 140 }
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 ExceptionHandlerServer::~ExceptionHandlerServer() { 253 ExceptionHandlerServer::~ExceptionHandlerServer() {
309 } 254 }
310 255
311 void ExceptionHandlerServer::SetPipeName(const std::wstring& pipe_name) { 256 void ExceptionHandlerServer::SetPipeName(const std::wstring& pipe_name) {
312 DCHECK(pipe_name_.empty()); 257 DCHECK(pipe_name_.empty());
313 DCHECK(!pipe_name.empty()); 258 DCHECK(!pipe_name.empty());
314 259
315 pipe_name_ = pipe_name; 260 pipe_name_ = pipe_name;
316 } 261 }
317 262
318 std::wstring ExceptionHandlerServer::CreatePipe() { 263 void ExceptionHandlerServer::InitializeWithInheritedDataForInitialClient(
264 const InitialClientData& initial_client_data,
265 Delegate* delegate) {
266 DCHECK(pipe_name_.empty());
319 DCHECK(!first_pipe_instance_.is_valid()); 267 DCHECK(!first_pipe_instance_.is_valid());
320 268
321 int tries = 5; 269 first_pipe_instance_.reset(initial_client_data.first_pipe_instance());
322 std::string pipe_name_base =
323 base::StringPrintf("\\\\.\\pipe\\crashpad_%d_", GetCurrentProcessId());
324 std::wstring pipe_name;
325 do {
326 pipe_name = base::UTF8ToUTF16(pipe_name_base + RandomString());
327 270
328 first_pipe_instance_.reset(CreateNamedPipeInstance(pipe_name, true)); 271 // TODO(scottmg): Vista+. Might need to pass through or possibly find an Nt*.
272 size_t bytes = sizeof(wchar_t) * _MAX_PATH + sizeof(FILE_NAME_INFO);
273 std::unique_ptr<uint8_t[]> data(new uint8_t[bytes]);
274 if (!GetFileInformationByHandleEx(first_pipe_instance_.get(),
275 FileNameInfo,
276 data.get(),
277 static_cast<DWORD>(bytes))) {
278 PLOG(FATAL) << "GetFileInformationByHandleEx";
279 }
280 FILE_NAME_INFO* file_name_info =
281 reinterpret_cast<FILE_NAME_INFO*>(data.get());
282 pipe_name_ =
283 L"\\\\.\\pipe" + std::wstring(file_name_info->FileName,
284 file_name_info->FileNameLength /
285 sizeof(file_name_info->FileName[0]));
329 286
330 // CreateNamedPipe() is documented as setting the error to 287 {
331 // ERROR_ACCESS_DENIED if FILE_FLAG_FIRST_PIPE_INSTANCE is specified and the 288 base::AutoLock lock(clients_lock_);
332 // pipe name is already in use. However it may set the error to other codes 289 internal::ClientData* client = new internal::ClientData(
333 // such as ERROR_PIPE_BUSY (if the pipe already exists and has reached its 290 port_.get(),
334 // maximum instance count) or ERROR_INVALID_PARAMETER (if the pipe already 291 delegate,
335 // exists and its attributes differ from those specified to 292 ScopedKernelHANDLE(initial_client_data.client_process()),
336 // CreateNamedPipe()). Some of these errors may be ambiguous: for example, 293 ScopedKernelHANDLE(initial_client_data.request_crash_dump()),
337 // ERROR_INVALID_PARAMETER may also occur if CreateNamedPipe() is called 294 ScopedKernelHANDLE(initial_client_data.request_non_crash_dump()),
338 // incorrectly even in the absence of an existing pipe by the same name. 295 ScopedKernelHANDLE(initial_client_data.non_crash_dump_completed()),
339 // 296 initial_client_data.crash_exception_information(),
340 // Rather than chasing down all of the possible errors that might indicate 297 initial_client_data.non_crash_exception_information(),
341 // that a pipe name is already in use, retry up to a few times on any error. 298 initial_client_data.debug_critical_section_address(),
342 } while (!first_pipe_instance_.is_valid() && --tries); 299 &OnCrashDumpEvent,
343 300 &OnNonCrashDumpEvent,
344 PCHECK(first_pipe_instance_.is_valid()) << "CreateNamedPipe"; 301 &OnProcessEnd);
345 302 clients_.insert(client);
346 SetPipeName(pipe_name); 303 }
347 return pipe_name;
348 } 304 }
349 305
350 void ExceptionHandlerServer::Run(Delegate* delegate) { 306 void ExceptionHandlerServer::Run(Delegate* delegate) {
351 uint64_t shutdown_token = base::RandUint64(); 307 uint64_t shutdown_token = base::RandUint64();
352 ScopedKernelHANDLE thread_handles[kPipeInstances]; 308 ScopedKernelHANDLE thread_handles[kPipeInstances];
353 for (size_t i = 0; i < arraysize(thread_handles); ++i) { 309 for (size_t i = 0; i < arraysize(thread_handles); ++i) {
354 HANDLE pipe; 310 HANDLE pipe;
355 if (first_pipe_instance_.is_valid()) { 311 if (first_pipe_instance_.is_valid()) {
356 pipe = first_pipe_instance_.release(); 312 pipe = first_pipe_instance_.release();
357 } else { 313 } else {
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 << message.shutdown.token; 406 << message.shutdown.token;
451 return false; 407 return false;
452 } 408 }
453 ServerToClientMessage shutdown_response = {}; 409 ServerToClientMessage shutdown_response = {};
454 LoggingWriteFile(service_context.pipe(), 410 LoggingWriteFile(service_context.pipe(),
455 &shutdown_response, 411 &shutdown_response,
456 sizeof(shutdown_response)); 412 sizeof(shutdown_response));
457 return true; 413 return true;
458 } 414 }
459 415
416 case ClientToServerMessage::kPing: {
417 // No action required, the fact that the message was processed is
418 // sufficient.
419 ServerToClientMessage shutdown_response = {};
420 LoggingWriteFile(service_context.pipe(),
421 &shutdown_response,
422 sizeof(shutdown_response));
423 return false;
424 }
425
460 case ClientToServerMessage::kRegister: 426 case ClientToServerMessage::kRegister:
461 // Handled below. 427 // Handled below.
462 break; 428 break;
463 429
464 default: 430 default:
465 LOG(ERROR) << "unhandled message type: " << message.type; 431 LOG(ERROR) << "unhandled message type: " << message.type;
466 return false; 432 return false;
467 } 433 }
468 434
469 if (message.registration.version != RegistrationRequest::kMessageVersion) { 435 if (message.registration.version != RegistrationRequest::kMessageVersion) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 } 472 }
507 } 473 }
508 474
509 internal::ClientData* client; 475 internal::ClientData* client;
510 { 476 {
511 base::AutoLock lock(*service_context.clients_lock()); 477 base::AutoLock lock(*service_context.clients_lock());
512 client = new internal::ClientData( 478 client = new internal::ClientData(
513 service_context.port(), 479 service_context.port(),
514 service_context.delegate(), 480 service_context.delegate(),
515 ScopedKernelHANDLE(client_process), 481 ScopedKernelHANDLE(client_process),
482 ScopedKernelHANDLE(
483 CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
484 ScopedKernelHANDLE(
485 CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
486 ScopedKernelHANDLE(
487 CreateEvent(nullptr, false /* auto reset */, false, nullptr)),
516 message.registration.crash_exception_information, 488 message.registration.crash_exception_information,
517 message.registration.non_crash_exception_information, 489 message.registration.non_crash_exception_information,
518 message.registration.critical_section_address, 490 message.registration.critical_section_address,
519 &OnCrashDumpEvent, 491 &OnCrashDumpEvent,
520 &OnNonCrashDumpEvent, 492 &OnNonCrashDumpEvent,
521 &OnProcessEnd); 493 &OnProcessEnd);
522 service_context.clients()->insert(client); 494 service_context.clients()->insert(client);
523 } 495 }
524 496
525 // Duplicate the events back to the client so they can request a dump. 497 // Duplicate the events back to the client so they can request a dump.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 void __stdcall ExceptionHandlerServer::OnProcessEnd(void* ctx, BOOLEAN) { 568 void __stdcall ExceptionHandlerServer::OnProcessEnd(void* ctx, BOOLEAN) {
597 // This function is executed on the thread pool. 569 // This function is executed on the thread pool.
598 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx); 570 internal::ClientData* client = reinterpret_cast<internal::ClientData*>(ctx);
599 base::AutoLock lock(*client->lock()); 571 base::AutoLock lock(*client->lock());
600 572
601 // Post back to the main thread to have it delete this client record. 573 // Post back to the main thread to have it delete this client record.
602 PostQueuedCompletionStatus(client->port(), 0, ULONG_PTR(client), nullptr); 574 PostQueuedCompletionStatus(client->port(), 0, ULONG_PTR(client), nullptr);
603 } 575 }
604 576
605 } // namespace crashpad 577 } // namespace crashpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698