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

Side by Side Diff: util/mach/child_port_handshake.cc

Issue 1408473002: ChildPortHandshake: allow receive rights to be received (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Address review feedback Created 5 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
« no previous file with comments | « util/mach/child_port_handshake.h ('k') | util/mach/child_port_handshake_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Crashpad Authors. All rights reserved. 1 // Copyright 2014 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,
(...skipping 14 matching lines...) Expand all
25 #include <algorithm> 25 #include <algorithm>
26 26
27 #include "base/logging.h" 27 #include "base/logging.h"
28 #include "base/mac/mach_logging.h" 28 #include "base/mac/mach_logging.h"
29 #include "base/mac/scoped_mach_port.h" 29 #include "base/mac/scoped_mach_port.h"
30 #include "base/posix/eintr_wrapper.h" 30 #include "base/posix/eintr_wrapper.h"
31 #include "base/rand_util.h" 31 #include "base/rand_util.h"
32 #include "base/strings/stringprintf.h" 32 #include "base/strings/stringprintf.h"
33 #include "util/file/file_io.h" 33 #include "util/file/file_io.h"
34 #include "util/mach/child_port.h" 34 #include "util/mach/child_port.h"
35 #include "util/mach/child_port_server.h"
35 #include "util/mach/mach_extensions.h" 36 #include "util/mach/mach_extensions.h"
36 #include "util/mach/mach_message.h" 37 #include "util/mach/mach_message.h"
37 #include "util/mach/mach_message_server.h" 38 #include "util/mach/mach_message_server.h"
38 #include "util/misc/implicit_cast.h" 39 #include "util/misc/implicit_cast.h"
39 40
40 namespace crashpad { 41 namespace crashpad {
42 namespace {
41 43
42 ChildPortHandshake::ChildPortHandshake() 44 class ChildPortHandshakeServer final : public ChildPortServer::Interface {
45 public:
46 ChildPortHandshakeServer();
47 ~ChildPortHandshakeServer();
48
49 mach_port_t RunServer(base::ScopedFD server_write_fd,
50 ChildPortHandshake::PortRightType port_right_type);
51
52 private:
53 // ChildPortServer::Interface:
54 kern_return_t HandleChildPortCheckIn(child_port_server_t server,
55 child_port_token_t token,
56 mach_port_t port,
57 mach_msg_type_name_t right_type,
58 const mach_msg_trailer_t* trailer,
59 bool* destroy_request) override;
60
61 child_port_token_t token_;
62 mach_port_t port_;
63 mach_msg_type_name_t right_type_;
64 bool checked_in_;
65
66 DISALLOW_COPY_AND_ASSIGN(ChildPortHandshakeServer);
67 };
68
69 ChildPortHandshakeServer::ChildPortHandshakeServer()
43 : token_(0), 70 : token_(0),
44 pipe_read_(), 71 port_(MACH_PORT_NULL),
45 pipe_write_(), 72 right_type_(MACH_MSG_TYPE_PORT_NONE),
46 child_port_(MACH_PORT_NULL),
47 checked_in_(false) { 73 checked_in_(false) {
48 // Use socketpair() instead of pipe(). There is no way to suppress SIGPIPE on
49 // pipes in Mac OS X 10.6, because the F_SETNOSIGPIPE fcntl() command was not
50 // introduced until 10.7.
51 int pipe_fds[2];
52 PCHECK(socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_fds) == 0)
53 << "socketpair";
54
55 pipe_read_.reset(pipe_fds[0]);
56 pipe_write_.reset(pipe_fds[1]);
57
58 // Simulate pipe() semantics by shutting down the “wrong” sides of the socket.
59 PCHECK(shutdown(pipe_write_.get(), SHUT_RD) == 0) << "shutdown";
60 PCHECK(shutdown(pipe_read_.get(), SHUT_WR) == 0) << "shutdown";
61
62 // SIGPIPE is undesirable when writing to this pipe. Allow broken-pipe writes
63 // to fail with EPIPE instead.
64 const int value = 1;
65 PCHECK(setsockopt(
66 pipe_write_.get(), SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value)) == 0)
67 << "setsockopt";
68 } 74 }
69 75
70 ChildPortHandshake::~ChildPortHandshake() { 76 ChildPortHandshakeServer::~ChildPortHandshakeServer() {
71 } 77 }
72 78
73 int ChildPortHandshake::ReadPipeFD() const { 79 mach_port_t ChildPortHandshakeServer::RunServer(
74 DCHECK_NE(pipe_read_.get(), -1); 80 base::ScopedFD server_write_fd,
75 return pipe_read_.get(); 81 ChildPortHandshake::PortRightType port_right_type) {
76 } 82 DCHECK_EQ(port_, kMachPortNull);
77 83 DCHECK(!checked_in_);
78 mach_port_t ChildPortHandshake::RunServer() { 84 DCHECK(server_write_fd.is_valid());
79 DCHECK_NE(pipe_read_.get(), -1);
80 pipe_read_.reset();
81
82 // Transfer ownership of the write pipe into this method’s scope.
83 base::ScopedFD pipe_write_owner = pipe_write_.Pass();
84 85
85 // Initialize the token and share it with the client via the pipe. 86 // Initialize the token and share it with the client via the pipe.
86 token_ = base::RandUint64(); 87 token_ = base::RandUint64();
87 int pipe_write = pipe_write_owner.get(); 88 if (!LoggingWriteFile(server_write_fd.get(), &token_, sizeof(token_))) {
88 if (!LoggingWriteFile(pipe_write, &token_, sizeof(token_))) {
89 LOG(WARNING) << "no client check-in"; 89 LOG(WARNING) << "no client check-in";
90 return MACH_PORT_NULL; 90 return MACH_PORT_NULL;
91 } 91 }
92 92
93 // Create a unique name for the bootstrap service mapping. Make it unguessable 93 // Create a unique name for the bootstrap service mapping. Make it unguessable
94 // to prevent outsiders from grabbing the name first, which would cause 94 // to prevent outsiders from grabbing the name first, which would cause
95 // bootstrap_check_in() to fail. 95 // bootstrap_check_in() to fail.
96 uint64_t thread_id; 96 uint64_t thread_id;
97 errno = pthread_threadid_np(pthread_self(), &thread_id); 97 errno = pthread_threadid_np(pthread_self(), &thread_id);
98 PCHECK(errno == 0) << "pthread_threadid_np"; 98 PCHECK(errno == 0) << "pthread_threadid_np";
99 std::string service_name = base::StringPrintf( 99 std::string service_name = base::StringPrintf(
100 "com.googlecode.crashpad.child_port_handshake.%d.%llu.%016llx", 100 "com.googlecode.crashpad.child_port_handshake.%d.%llu.%016llx",
101 getpid(), 101 getpid(),
102 thread_id, 102 thread_id,
103 base::RandUint64()); 103 base::RandUint64());
104 104
105 // Check the new service in with the bootstrap server, obtaining a receive 105 // Check the new service in with the bootstrap server, obtaining a receive
106 // right for it. 106 // right for it.
107 base::mac::ScopedMachReceiveRight server_port(BootstrapCheckIn(service_name)); 107 base::mac::ScopedMachReceiveRight server_port(BootstrapCheckIn(service_name));
108 CHECK(server_port.is_valid()); 108 CHECK(server_port.is_valid());
109 109
110 // Share the service name with the client via the pipe. 110 // Share the service name with the client via the pipe.
111 uint32_t service_name_length = service_name.size(); 111 uint32_t service_name_length = service_name.size();
112 if (!LoggingWriteFile( 112 if (!LoggingWriteFile(server_write_fd.get(),
113 pipe_write, &service_name_length, sizeof(service_name_length))) { 113 &service_name_length,
114 sizeof(service_name_length))) {
114 LOG(WARNING) << "no client check-in"; 115 LOG(WARNING) << "no client check-in";
115 return MACH_PORT_NULL; 116 return MACH_PORT_NULL;
116 } 117 }
117 118
118 if (!LoggingWriteFile( 119 if (!LoggingWriteFile(
119 pipe_write, service_name.c_str(), service_name_length)) { 120 server_write_fd.get(), service_name.c_str(), service_name_length)) {
120 LOG(WARNING) << "no client check-in"; 121 LOG(WARNING) << "no client check-in";
121 return MACH_PORT_NULL; 122 return MACH_PORT_NULL;
122 } 123 }
123 124
124 // A kqueue cannot monitor a raw Mach receive right with EVFILT_MACHPORT. It 125 // A kqueue cannot monitor a raw Mach receive right with EVFILT_MACHPORT. It
125 // requires a port set. Create a new port set and add the receive right to it. 126 // requires a port set. Create a new port set and add the receive right to it.
126 base::mac::ScopedMachPortSet server_port_set( 127 base::mac::ScopedMachPortSet server_port_set(
127 NewMachPort(MACH_PORT_RIGHT_PORT_SET)); 128 NewMachPort(MACH_PORT_RIGHT_PORT_SET));
128 CHECK(server_port_set.is_valid()); 129 CHECK(server_port_set.is_valid());
129 130
(...skipping 10 matching lines...) Expand all
140 141
141 struct kevent changelist[2]; 142 struct kevent changelist[2];
142 EV_SET(&changelist[0], 143 EV_SET(&changelist[0],
143 server_port_set.get(), 144 server_port_set.get(),
144 EVFILT_MACHPORT, 145 EVFILT_MACHPORT,
145 EV_ADD | EV_CLEAR, 146 EV_ADD | EV_CLEAR,
146 0, 147 0,
147 0, 148 0,
148 nullptr); 149 nullptr);
149 EV_SET(&changelist[1], 150 EV_SET(&changelist[1],
150 pipe_write, 151 server_write_fd.get(),
151 EVFILT_WRITE, 152 EVFILT_WRITE,
152 EV_ADD | EV_CLEAR, 153 EV_ADD | EV_CLEAR,
153 0, 154 0,
154 0, 155 0,
155 nullptr); 156 nullptr);
156 int rv = HANDLE_EINTR( 157 int rv = HANDLE_EINTR(
157 kevent(kq.get(), changelist, arraysize(changelist), nullptr, 0, nullptr)); 158 kevent(kq.get(), changelist, arraysize(changelist), nullptr, 0, nullptr));
158 PCHECK(rv != -1) << "kevent"; 159 PCHECK(rv != -1) << "kevent";
159 160
160 ChildPortServer child_port_server(this); 161 ChildPortServer child_port_server(this);
161 162
162 bool blocking = true; 163 bool blocking = true;
163 DCHECK(!checked_in_); 164 DCHECK(!checked_in_);
164 while (!checked_in_) { 165 while (!checked_in_) {
165 DCHECK_EQ(child_port_, kMachPortNull); 166 DCHECK_EQ(port_, kMachPortNull);
166 167
167 // Get a kevent from the kqueue. Block while waiting for an event unless the 168 // Get a kevent from the kqueue. Block while waiting for an event unless the
168 // write pipe has arrived at EOF, in which case the kevent() should be 169 // write pipe has arrived at EOF, in which case the kevent() should be
169 // nonblocking. Although the client sends its check-in message before 170 // nonblocking. Although the client sends its check-in message before
170 // closing the read side of the pipe, this organization allows the events to 171 // closing the read side of the pipe, this organization allows the events to
171 // be delivered out of order and the check-in message will still be 172 // be delivered out of order and the check-in message will still be
172 // processed. 173 // processed.
173 struct kevent event; 174 struct kevent event;
174 const timespec nonblocking_timeout = {}; 175 const timespec nonblocking_timeout = {};
175 const timespec* timeout = blocking ? nullptr : &nonblocking_timeout; 176 const timespec* timeout = blocking ? nullptr : &nonblocking_timeout;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 } 224 }
224 225
225 case EVFILT_WRITE: 226 case EVFILT_WRITE:
226 // The write pipe is ready to be written to, or it’s at EOF. The former 227 // The write pipe is ready to be written to, or it’s at EOF. The former
227 // case is uninteresting, but a notification for this may be presented 228 // case is uninteresting, but a notification for this may be presented
228 // because the write pipe will be ready to be written to, at the latest, 229 // because the write pipe will be ready to be written to, at the latest,
229 // when the client reads its messages from the read side of the same 230 // when the client reads its messages from the read side of the same
230 // pipe. Ignore that case. Multiple notifications for that situation 231 // pipe. Ignore that case. Multiple notifications for that situation
231 // will not be generated because edge triggering (EV_CLEAR) is used 232 // will not be generated because edge triggering (EV_CLEAR) is used
232 // above. 233 // above.
233 DCHECK_EQ(implicit_cast<int>(event.ident), pipe_write); 234 DCHECK_EQ(implicit_cast<int>(event.ident), server_write_fd.get());
234 if (event.flags & EV_EOF) { 235 if (event.flags & EV_EOF) {
235 // There are no readers attached to the write pipe. The client has 236 // There are no readers attached to the write pipe. The client has
236 // closed its side of the pipe. There can be one last shot at 237 // closed its side of the pipe. There can be one last shot at
237 // receiving messages, in case the check-in message is delivered 238 // receiving messages, in case the check-in message is delivered
238 // out of order, after the EOF notification. 239 // out of order, after the EOF notification.
239 blocking = false; 240 blocking = false;
240 } 241 }
241 break; 242 break;
242 243
243 default: 244 default:
244 NOTREACHED(); 245 NOTREACHED();
245 break; 246 break;
246 } 247 }
247 } 248 }
248 249
249 mach_port_t child_port = MACH_PORT_NULL; 250 if (port_ == MACH_PORT_NULL) {
250 std::swap(child_port_, child_port); 251 return MACH_PORT_NULL;
251 return child_port; 252 }
253
254 bool mismatch = false;
255 switch (port_right_type) {
256 case ChildPortHandshake::PortRightType::kReceiveRight:
257 if (right_type_ != MACH_MSG_TYPE_PORT_RECEIVE) {
258 LOG(ERROR) << "expected receive right, observed " << right_type_;
259 mismatch = true;
260 }
261 break;
262 case ChildPortHandshake::PortRightType::kSendRight:
263 if (right_type_ != MACH_MSG_TYPE_PORT_SEND &&
264 right_type_ != MACH_MSG_TYPE_PORT_SEND_ONCE) {
265 LOG(ERROR) << "expected send or send-once right, observed "
266 << right_type_;
267 mismatch = true;
268 }
269 break;
270 }
271
272 if (mismatch) {
273 MachMessageDestroyReceivedPort(port_, right_type_);
274 port_ = MACH_PORT_NULL;
275 return MACH_PORT_NULL;
276 }
277
278 mach_port_t port = MACH_PORT_NULL;
279 std::swap(port_, port);
280 return port;
252 } 281 }
253 282
254 kern_return_t ChildPortHandshake::HandleChildPortCheckIn( 283 kern_return_t ChildPortHandshakeServer::HandleChildPortCheckIn(
255 child_port_server_t server, 284 child_port_server_t server,
256 const child_port_token_t token, 285 const child_port_token_t token,
257 mach_port_t port, 286 mach_port_t port,
258 mach_msg_type_name_t right_type, 287 mach_msg_type_name_t right_type,
259 const mach_msg_trailer_t* trailer, 288 const mach_msg_trailer_t* trailer,
260 bool* destroy_request) { 289 bool* destroy_request) {
261 DCHECK_EQ(child_port_, kMachPortNull); 290 DCHECK_EQ(port_, kMachPortNull);
291 DCHECK(!checked_in_);
262 292
263 if (token != token_) { 293 if (token != token_) {
264 // If the token’s not correct, someone’s attempting to spoof the legitimate 294 // If the token’s not correct, someone’s attempting to spoof the legitimate
265 // client. 295 // client.
266 LOG(WARNING) << "ignoring incorrect token"; 296 LOG(WARNING) << "ignoring incorrect token";
267 *destroy_request = true; 297 *destroy_request = true;
268 } else { 298 } else {
269 checked_in_ = true; 299 checked_in_ = true;
270 300
271 if (right_type == MACH_MSG_TYPE_PORT_RECEIVE) { 301 if (right_type != MACH_MSG_TYPE_PORT_RECEIVE &&
272 // The message needs to carry a send right or a send-once right. This 302 right_type != MACH_MSG_TYPE_PORT_SEND &&
273 // isn’t a strict requirement of the protocol, but users of this class 303 right_type != MACH_MSG_TYPE_PORT_SEND_ONCE) {
274 // expect a send right or a send-once right, both of which can be managed 304 // The message needs to carry a receive, send, or send-once right.
275 // by base::mac::ScopedMachSendRight. It is invalid to store a receive 305 LOG(ERROR) << "invalid right type " << right_type;
276 // right in that scoper.
277 LOG(WARNING) << "ignoring MACH_MSG_TYPE_PORT_RECEIVE";
278 *destroy_request = true; 306 *destroy_request = true;
279 } else { 307 } else {
280 // Communicate the child port back to the RunServer(). 308 // Communicate the child port and right type back to the RunServer().
281 // *destroy_request is left at false, because RunServer() needs the right 309 // *destroy_request is left at false, because RunServer() needs the right
282 // to remain intact. It gives ownership of the right to its caller. 310 // to remain intact. It gives ownership of the right to its caller.
283 child_port_ = port; 311 port_ = port;
312 right_type_ = right_type;
284 } 313 }
285 } 314 }
286 315
287 // This is a MIG simpleroutine, there is no reply message. 316 // This is a MIG simpleroutine, there is no reply message.
288 return MIG_NO_REPLY; 317 return MIG_NO_REPLY;
289 } 318 }
290 319
320 } // namespace
321
322 ChildPortHandshake::ChildPortHandshake()
323 : client_read_fd_(),
324 server_write_fd_() {
325 // Use socketpair() instead of pipe(). There is no way to suppress SIGPIPE on
326 // pipes in Mac OS X 10.6, because the F_SETNOSIGPIPE fcntl() command was not
327 // introduced until 10.7.
328 int pipe_fds[2];
329 PCHECK(socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_fds) == 0)
330 << "socketpair";
331
332 client_read_fd_.reset(pipe_fds[0]);
333 server_write_fd_.reset(pipe_fds[1]);
334
335 // Simulate pipe() semantics by shutting down the “wrong” sides of the socket.
336 PCHECK(shutdown(server_write_fd_.get(), SHUT_RD) == 0) << "shutdown SHUT_RD";
337 PCHECK(shutdown(client_read_fd_.get(), SHUT_WR) == 0) << "shutdown SHUT_WR";
338
339 // SIGPIPE is undesirable when writing to this pipe. Allow broken-pipe writes
340 // to fail with EPIPE instead.
341 const int value = 1;
342 PCHECK(setsockopt(server_write_fd_.get(),
343 SOL_SOCKET,
344 SO_NOSIGPIPE,
345 &value,
346 sizeof(value)) == 0) << "setsockopt";
347 }
348
349 ChildPortHandshake::~ChildPortHandshake() {
350 }
351
352 base::ScopedFD ChildPortHandshake::ClientReadFD() {
353 DCHECK(client_read_fd_.is_valid());
354 return client_read_fd_.Pass();
355 }
356
357 base::ScopedFD ChildPortHandshake::ServerWriteFD() {
358 DCHECK(server_write_fd_.is_valid());
359 return server_write_fd_.Pass();
360 }
361
362 mach_port_t ChildPortHandshake::RunServer(PortRightType port_right_type) {
363 client_read_fd_.reset();
364 return RunServerForFD(server_write_fd_.Pass(), port_right_type);
365 }
366
367 bool ChildPortHandshake::RunClient(mach_port_t port,
368 mach_msg_type_name_t right_type) {
369 server_write_fd_.reset();
370 return RunClientForFD(client_read_fd_.Pass(), port, right_type);
371 }
372
291 // static 373 // static
292 void ChildPortHandshake::RunClient(int pipe_read, 374 mach_port_t ChildPortHandshake::RunServerForFD(base::ScopedFD server_write_fd,
293 mach_port_t port, 375 PortRightType port_right_type) {
294 mach_msg_type_name_t right_type) { 376 ChildPortHandshakeServer server;
295 base::ScopedFD pipe_read_owner(pipe_read); 377 return server.RunServer(server_write_fd.Pass(), port_right_type);
378 }
379
380 // static
381 bool ChildPortHandshake::RunClientForFD(base::ScopedFD client_read_fd,
382 mach_port_t port,
383 mach_msg_type_name_t right_type) {
384 DCHECK(client_read_fd.is_valid());
296 385
297 // Read the token and the service name from the read side of the pipe. 386 // Read the token and the service name from the read side of the pipe.
298 child_port_token_t token; 387 child_port_token_t token;
299 std::string service_name; 388 std::string service_name;
300 RunClientInternal_ReadPipe(pipe_read, &token, &service_name); 389 if (!RunClientInternal_ReadPipe(
390 client_read_fd.get(), &token, &service_name)) {
391 return false;
392 }
301 393
302 // Look up the server and check in with it by providing the token and port. 394 // Look up the server and check in with it by providing the token and port.
303 RunClientInternal_SendCheckIn(service_name, token, port, right_type); 395 return RunClientInternal_SendCheckIn(service_name, token, port, right_type);
304 } 396 }
305 397
306 // static 398 // static
307 void ChildPortHandshake::RunClientInternal_ReadPipe(int pipe_read, 399 bool ChildPortHandshake::RunClientInternal_ReadPipe(int client_read_fd,
308 child_port_token_t* token, 400 child_port_token_t* token,
309 std::string* service_name) { 401 std::string* service_name) {
310 // Read the token from the pipe. 402 // Read the token from the pipe.
311 CheckedReadFile(pipe_read, token, sizeof(*token)); 403 if (!LoggingReadFile(client_read_fd, token, sizeof(*token))) {
404 return false;
405 }
312 406
313 // Read the service name from the pipe. 407 // Read the service name from the pipe.
314 uint32_t service_name_length; 408 uint32_t service_name_length;
315 CheckedReadFile(pipe_read, &service_name_length, sizeof(service_name_length)); 409 if (!LoggingReadFile(
410 client_read_fd, &service_name_length, sizeof(service_name_length))) {
411 return false;
412 }
316 413
317 service_name->resize(service_name_length); 414 service_name->resize(service_name_length);
318 if (!service_name->empty()) { 415 if (!service_name->empty() &&
319 CheckedReadFile(pipe_read, &(*service_name)[0], service_name_length); 416 !LoggingReadFile(
417 client_read_fd, &(*service_name)[0], service_name_length)) {
418 return false;
320 } 419 }
420
421 return true;
321 } 422 }
322 423
323 // static 424 // static
324 void ChildPortHandshake::RunClientInternal_SendCheckIn( 425 bool ChildPortHandshake::RunClientInternal_SendCheckIn(
325 const std::string& service_name, 426 const std::string& service_name,
326 child_port_token_t token, 427 child_port_token_t token,
327 mach_port_t port, 428 mach_port_t port,
328 mach_msg_type_name_t right_type) { 429 mach_msg_type_name_t right_type) {
329 // Get a send right to the server by looking up the service with the bootstrap 430 // Get a send right to the server by looking up the service with the bootstrap
330 // server by name. 431 // server by name.
331 base::mac::ScopedMachSendRight server_port(BootstrapLookUp(service_name)); 432 base::mac::ScopedMachSendRight server_port(BootstrapLookUp(service_name));
332 CHECK(server_port.is_valid()); 433 if (server_port == kMachPortNull) {
434 return false;
435 }
333 436
334 // Check in with the server. 437 // Check in with the server.
335 kern_return_t kr = 438 kern_return_t kr = child_port_check_in(
336 child_port_check_in(server_port.get(), token, port, right_type); 439 server_port.get(), token, port, right_type);
337 MACH_CHECK(kr == KERN_SUCCESS, kr) << "child_port_check_in"; 440 if (kr != KERN_SUCCESS) {
441 MACH_LOG(ERROR, kr) << "child_port_check_in";
442 return false;
443 }
444
445 return true;
338 } 446 }
339 447
340 } // namespace crashpad 448 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/mach/child_port_handshake.h ('k') | util/mach/child_port_handshake_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698