1 // Copyright 2014 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 #include "util/mach/mach_message_server.h"
16 
17 #include <mach/mach.h>
18 #include <stdint.h>
19 #include <string.h>
20 #include <sys/types.h>
21 
22 #include <set>
23 
24 #include "base/mac/scoped_mach_port.h"
25 #include "base/macros.h"
26 #include "base/stl_util.h"
27 #include "gtest/gtest.h"
28 #include "test/mac/mach_errors.h"
29 #include "test/mac/mach_multiprocess.h"
30 #include "util/file/file_io.h"
31 #include "util/mach/mach_extensions.h"
32 #include "util/mach/mach_message.h"
33 #include "util/misc/implicit_cast.h"
34 
35 namespace crashpad {
36 namespace test {
37 namespace {
38 
39 class TestMachMessageServer : public MachMessageServer::Interface,
40                               public MachMultiprocess {
41  public:
42   struct Options {
43     // The type of reply port that the client should put in its request message.
44     enum ReplyPortType {
45       // The normal reply port is the client’s local port, to which it holds
46       // a receive right. This allows the server to respond directly to the
47       // client. The client will expect a reply.
48       kReplyPortNormal,
49 
50       // Use MACH_PORT_NULL as the reply port, which the server should detect
51       // avoid attempting to send a message to, and return success. The client
52       // will not expect a reply.
53       kReplyPortNull,
54 
55       // Make the server see the reply port as a dead name by setting the reply
56       // port to a receive right and then destroying that right before the
57       // server processes the request. The server should return
58       // MACH_SEND_INVALID_DEST, and the client will not expect a reply.
59       kReplyPortDead,
60     };
61 
Optionscrashpad::test::__anon4bf00e5e0111::TestMachMessageServer::Options62     Options()
63         : expect_server_interface_method_called(true),
64           parent_wait_for_child_pipe(false),
65           server_options(MACH_MSG_OPTION_NONE),
66           server_persistent(MachMessageServer::kOneShot),
67           server_receive_large(MachMessageServer::kReceiveLargeError),
68           server_timeout_ms(kMachMessageTimeoutWaitIndefinitely),
69           server_mig_retcode(KERN_SUCCESS),
70           server_destroy_complex(true),
71           expect_server_destroyed_complex(true),
72           expect_server_result(KERN_SUCCESS),
73           expect_server_transaction_count(1),
74           child_wait_for_parent_pipe_early(false),
75           client_send_request_count(1),
76           client_send_complex(false),
77           client_send_large(false),
78           client_reply_port_type(kReplyPortNormal),
79           client_expect_reply(true),
80           child_send_all_requests_before_receiving_any_replies(false),
81           child_wait_for_parent_pipe_late(false) {
82     }
83 
84     // true if MachMessageServerFunction() is expected to be called.
85     bool expect_server_interface_method_called;
86 
87     // true if the parent should wait for the child to write a byte to the pipe
88     // as a signal that the child is ready for the parent to begin its side of
89     // the test. This is used for nonblocking tests, which require that there
90     // be something in the server’s queue before attempting a nonblocking
91     // receive if the receive is to be successful.
92     bool parent_wait_for_child_pipe;
93 
94     // Options to pass to MachMessageServer::Run() as the |options| parameter.
95     mach_msg_options_t server_options;
96 
97     // Whether the server should run in one-shot or persistent mode.
98     MachMessageServer::Persistent server_persistent;
99 
100     // The strategy for handling large messages.
101     MachMessageServer::ReceiveLarge server_receive_large;
102 
103     // The server’s timeout in milliseconds, or kMachMessageTimeoutNonblocking
104     // or kMachMessageTimeoutWaitIndefinitely.
105     mach_msg_timeout_t server_timeout_ms;
106 
107     // The return code that the server returns to the client via the
108     // mig_reply_error_t::RetCode field. A client would normally see this as
109     // a Mach RPC return value.
110     kern_return_t server_mig_retcode;
111 
112     // The value that the server function should set its destroy_complex_request
113     // parameter to. This is true if resources sent in complex request messages
114     // should be destroyed, and false if they should not be destroyed, assuming
115     // that the server function indicates success.
116     bool server_destroy_complex;
117 
118     // Whether to expect the server to destroy a complex message. Even if
119     // server_destroy_complex is false, a complex message will be destroyed if
120     // the MIG return code was unsuccessful.
121     bool expect_server_destroyed_complex;
122 
123     // The expected return value from MachMessageServer::Run().
124     kern_return_t expect_server_result;
125 
126     // The number of transactions that the server is expected to handle.
127     size_t expect_server_transaction_count;
128 
129     // true if the child should wait for the parent to signal that it’s ready
130     // for the child to begin sending requests via the pipe. This is done if the
131     // parent needs to perform operations on its receive port before the child
132     // should be permitted to send anything to it. Currently, this is used to
133     // allow the parent to ensure that the receive port’s queue length is high
134     // enough before the child begins attempting to fill it.
135     bool child_wait_for_parent_pipe_early;
136 
137     // The number of requests that the client should send to the server.
138     size_t client_send_request_count;
139 
140     // true if the client should send a complex message, one that carries a port
141     // descriptor in its body. Normally false.
142     bool client_send_complex;
143 
144     // true if the client should send a larger message than the server has
145     // allocated space to receive. The server’s response is directed by
146     // server_receive_large.
147     bool client_send_large;
148 
149     // The type of reply port that the client should provide in its request’s
150     // mach_msg_header_t::msgh_local_port, which will appear to the server as
151     // mach_msg_header_t::msgh_remote_port.
152     ReplyPortType client_reply_port_type;
153 
154     // true if the client should wait for a reply from the server. For
155     // non-normal reply ports or requests which the server responds to with no
156     // reply (MIG_NO_REPLY), the server will either not send a reply or not
157     // succeed in sending a reply, and the child process should not wait for
158     // one.
159     bool client_expect_reply;
160 
161     // true if the client should send all requests before attempting to receive
162     // any replies from the server. This is used for the persistent nonblocking
163     // test, which requires the client to fill the server’s queue before the
164     // server can attempt processing it.
165     bool child_send_all_requests_before_receiving_any_replies;
166 
167     // true if the child should wait to receive a byte from the parent before
168     // exiting. This can be used to keep a receive right in the child alive
169     // until the parent has a chance to verify that it’s holding a send right.
170     // Otherwise, the right might appear in the parent as a dead name if the
171     // child exited before the parent had a chance to examine it. This would be
172     // a race.
173     bool child_wait_for_parent_pipe_late;
174   };
175 
TestMachMessageServer(const Options & options)176   explicit TestMachMessageServer(const Options& options)
177       : MachMessageServer::Interface(),
178         MachMultiprocess(),
179         options_(options),
180         child_complex_message_port_(),
181         parent_complex_message_port_(MACH_PORT_NULL) {
182   }
183 
184   // Runs the test.
Test()185   void Test() {
186     EXPECT_EQ(replies_, requests_);
187     uint32_t start = requests_;
188 
189     Run();
190 
191     EXPECT_EQ(replies_, requests_);
192     EXPECT_EQ(requests_ - start, options_.expect_server_transaction_count);
193   }
194 
195   // MachMessageServerInterface:
196 
MachMessageServerFunction(const mach_msg_header_t * in,mach_msg_header_t * out,bool * destroy_complex_request)197   virtual bool MachMessageServerFunction(
198       const mach_msg_header_t* in,
199       mach_msg_header_t* out,
200       bool* destroy_complex_request) override {
201     *destroy_complex_request = options_.server_destroy_complex;
202 
203     EXPECT_TRUE(options_.expect_server_interface_method_called);
204     if (!options_.expect_server_interface_method_called) {
205       return false;
206     }
207 
208     struct ReceiveRequestMessage : public RequestMessage {
209       mach_msg_trailer_t trailer;
210     };
211 
212     struct ReceiveLargeRequestMessage : public LargeRequestMessage {
213       mach_msg_trailer_t trailer;
214     };
215 
216     const ReceiveRequestMessage* request =
217         reinterpret_cast<const ReceiveRequestMessage*>(in);
218     const mach_msg_bits_t expect_msgh_bits =
219         MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND, MACH_MSG_TYPE_MOVE_SEND) |
220         (options_.client_send_complex ? MACH_MSGH_BITS_COMPLEX : 0);
221     EXPECT_EQ(request->header.msgh_bits, expect_msgh_bits);
222     EXPECT_EQ(request->header.msgh_size,
223               options_.client_send_large ? sizeof(LargeRequestMessage)
224                                          : sizeof(RequestMessage));
225     if (options_.client_reply_port_type == Options::kReplyPortNormal) {
226       EXPECT_EQ(request->header.msgh_remote_port, RemotePort());
227     }
228     EXPECT_EQ(request->header.msgh_local_port, LocalPort());
229     EXPECT_EQ(request->header.msgh_id, kRequestMessageID);
230     if (options_.client_send_complex) {
231       EXPECT_EQ(request->body.msgh_descriptor_count, 1u);
232       EXPECT_NE(request->port_descriptor.name, kMachPortNull);
233       parent_complex_message_port_ = request->port_descriptor.name;
234       EXPECT_EQ(request->port_descriptor.disposition,
235                 implicit_cast<mach_msg_type_name_t>(MACH_MSG_TYPE_MOVE_SEND));
236       EXPECT_EQ(
237           request->port_descriptor.type,
238           implicit_cast<mach_msg_descriptor_type_t>(MACH_MSG_PORT_DESCRIPTOR));
239     } else {
240       EXPECT_EQ(request->body.msgh_descriptor_count, 0u);
241       EXPECT_EQ(request->port_descriptor.name, kMachPortNull);
242       EXPECT_EQ(request->port_descriptor.disposition, 0u);
243       EXPECT_EQ(request->port_descriptor.type, 0u);
244     }
245     EXPECT_EQ(memcmp(&request->ndr, &NDR_record, sizeof(NDR_record)), 0);
246     EXPECT_EQ(request->number, requests_);
247 
248     // Look for the trailer in the right spot, depending on whether the request
249     // message was a RequestMessage or a LargeRequestMessage.
250     const mach_msg_trailer_t* trailer;
251     if (options_.client_send_large) {
252       const ReceiveLargeRequestMessage* large_request =
253           reinterpret_cast<const ReceiveLargeRequestMessage*>(request);
254       for (size_t index = 0; index < sizeof(large_request->data); ++index) {
255         EXPECT_EQ(large_request->data[index], '!');
256       }
257       trailer = &large_request->trailer;
258     } else {
259       trailer = &request->trailer;
260     }
261 
262     EXPECT_EQ(
263         trailer->msgh_trailer_type,
264         implicit_cast<mach_msg_trailer_type_t>(MACH_MSG_TRAILER_FORMAT_0));
265     EXPECT_EQ(trailer->msgh_trailer_size, MACH_MSG_TRAILER_MINIMUM_SIZE);
266 
267     ++requests_;
268 
269     ReplyMessage* reply = reinterpret_cast<ReplyMessage*>(out);
270     reply->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
271     reply->Head.msgh_size = sizeof(*reply);
272     reply->Head.msgh_remote_port = request->header.msgh_remote_port;
273     reply->Head.msgh_local_port = MACH_PORT_NULL;
274     reply->Head.msgh_id = kReplyMessageID;
275     reply->NDR = NDR_record;
276     reply->RetCode = options_.server_mig_retcode;
277     reply->number = replies_++;
278 
279     return true;
280   }
281 
MachMessageServerRequestIDs()282   std::set<mach_msg_id_t> MachMessageServerRequestIDs() override {
283     static constexpr mach_msg_id_t request_ids[] = {kRequestMessageID};
284     return std::set<mach_msg_id_t>(&request_ids[0],
285                                    &request_ids[base::size(request_ids)]);
286   }
287 
MachMessageServerRequestSize()288   mach_msg_size_t MachMessageServerRequestSize() override {
289     return sizeof(RequestMessage);
290   }
291 
MachMessageServerReplySize()292   mach_msg_size_t MachMessageServerReplySize() override {
293     return sizeof(ReplyMessage);
294   }
295 
296  private:
297   struct RequestMessage : public mach_msg_base_t {
298     // If body.msgh_descriptor_count is 0, port_descriptor will still be
299     // present, but it will be zeroed out. It wouldn’t normally be present in a
300     // message froma MIG-generated interface, but it’s harmless and simpler to
301     // leave it here and just treat it as more data.
302     mach_msg_port_descriptor_t port_descriptor;
303 
304     NDR_record_t ndr;
305     uint32_t number;
306   };
307 
308   // LargeRequestMessage is larger enough than a regular RequestMessage to
309   // ensure that whatever buffer was allocated to receive a RequestMessage is
310   // not large enough to receive a LargeRequestMessage.
311   struct LargeRequestMessage : public RequestMessage {
312     uint8_t data[4 * PAGE_SIZE];
313   };
314 
315   struct ReplyMessage : public mig_reply_error_t {
316     uint32_t number;
317   };
318 
319   // MachMultiprocess:
320 
MachMultiprocessParent()321   void MachMultiprocessParent() override {
322     mach_port_t local_port = LocalPort();
323 
324     kern_return_t kr;
325     if (options_.child_send_all_requests_before_receiving_any_replies) {
326       // On OS X 10.10, the queue limit of a new Mach port seems to be 2 by
327       // default, which is below the value of MACH_PORT_QLIMIT_DEFAULT. Set the
328       // port’s queue limit explicitly here.
329       mach_port_limits limits = {};
330       limits.mpl_qlimit = MACH_PORT_QLIMIT_DEFAULT;
331       kr = mach_port_set_attributes(mach_task_self(),
332                                     local_port,
333                                     MACH_PORT_LIMITS_INFO,
334                                     reinterpret_cast<mach_port_info_t>(&limits),
335                                     MACH_PORT_LIMITS_INFO_COUNT);
336       ASSERT_EQ(kr, KERN_SUCCESS)
337           << MachErrorMessage(kr, "mach_port_set_attributes");
338     }
339 
340     if (options_.child_wait_for_parent_pipe_early) {
341       // Tell the child to begin sending messages.
342       char c = '\0';
343       CheckedWriteFile(WritePipeHandle(), &c, 1);
344     }
345 
346     if (options_.parent_wait_for_child_pipe) {
347       // Wait until the child is done sending what it’s going to send.
348       char c;
349       CheckedReadFileExactly(ReadPipeHandle(), &c, 1);
350       EXPECT_EQ(c, '\0');
351     }
352 
353     ASSERT_EQ((kr = MachMessageServer::Run(this,
354                                            local_port,
355                                            options_.server_options,
356                                            options_.server_persistent,
357                                            options_.server_receive_large,
358                                            options_.server_timeout_ms)),
359               options_.expect_server_result)
360         << MachErrorMessage(kr, "MachMessageServer");
361 
362     if (options_.client_send_complex) {
363       EXPECT_NE(parent_complex_message_port_, kMachPortNull);
364       mach_port_type_t type;
365 
366       if (!options_.expect_server_destroyed_complex) {
367         // MachMessageServer should not have destroyed the resources sent in the
368         // complex request message.
369         kr = mach_port_type(
370             mach_task_self(), parent_complex_message_port_, &type);
371         EXPECT_EQ(kr, KERN_SUCCESS) << MachErrorMessage(kr, "mach_port_type");
372         EXPECT_EQ(type, MACH_PORT_TYPE_SEND);
373 
374         // Destroy the resources here.
375         kr = mach_port_deallocate(mach_task_self(),
376                                   parent_complex_message_port_);
377         EXPECT_EQ(kr, KERN_SUCCESS)
378             << MachErrorMessage(kr, "mach_port_deallocate");
379       }
380 
381       // The kernel won’t have reused the same name for another Mach port in
382       // this task so soon. It’s possible that something else in this task could
383       // have reused the name, but it’s unlikely for that to have happened in
384       // this test environment.
385       kr =
386           mach_port_type(mach_task_self(), parent_complex_message_port_, &type);
387       EXPECT_EQ(kr, KERN_INVALID_NAME)
388           << MachErrorMessage(kr, "mach_port_type");
389     }
390 
391     if (options_.child_wait_for_parent_pipe_late) {
392       // Let the child know it’s safe to exit.
393       char c = '\0';
394       CheckedWriteFile(WritePipeHandle(), &c, 1);
395     }
396   }
397 
MachMultiprocessChild()398   void MachMultiprocessChild() override {
399     if (options_.child_wait_for_parent_pipe_early) {
400       // Wait until the parent is done setting things up on its end.
401       char c;
402       CheckedReadFileExactly(ReadPipeHandle(), &c, 1);
403       EXPECT_EQ(c, '\0');
404     }
405 
406     for (size_t index = 0;
407          index < options_.client_send_request_count;
408          ++index) {
409       if (options_.child_send_all_requests_before_receiving_any_replies) {
410         // For this test, all of the messages need to go into the queue before
411         // the parent is allowed to start processing them. Don’t attempt to
412         // process replies before all of the requests are sent, because the
413         // server won’t have sent any replies until all of the requests are in
414         // its queue.
415         ASSERT_NO_FATAL_FAILURE(ChildSendRequest());
416       } else {
417         ASSERT_NO_FATAL_FAILURE(ChildSendRequestAndWaitForReply());
418       }
419     }
420 
421     if (options_.parent_wait_for_child_pipe &&
422         options_.child_send_all_requests_before_receiving_any_replies) {
423       // Now that all of the requests have been sent, let the parent know that
424       // it’s safe to begin processing them, and then wait for the replies.
425       ASSERT_NO_FATAL_FAILURE(ChildNotifyParentViaPipe());
426 
427       for (size_t index = 0;
428            index < options_.client_send_request_count;
429            ++index) {
430         ASSERT_NO_FATAL_FAILURE(ChildWaitForReply());
431       }
432     }
433 
434     if (options_.child_wait_for_parent_pipe_late) {
435       char c;
436       CheckedReadFileExactly(ReadPipeHandle(), &c, 1);
437       ASSERT_EQ(c, '\0');
438     }
439   }
440 
441   // In the child process, sends a request message to the server.
ChildSendRequest()442   void ChildSendRequest() {
443     // local_receive_port_owner will the receive right that is created in this
444     // scope and intended to be destroyed when leaving this scope, after it has
445     // been carried in a Mach message.
446     base::mac::ScopedMachReceiveRight local_receive_port_owner;
447 
448     // A LargeRequestMessage is always allocated, but the message that will be
449     // sent will be a normal RequestMessage due to the msgh_size field
450     // indicating the size of the smaller base structure unless
451     // options_.client_send_large is true.
452     LargeRequestMessage request = {};
453 
454     request.header.msgh_bits =
455         MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND) |
456         (options_.client_send_complex ? MACH_MSGH_BITS_COMPLEX : 0);
457     request.header.msgh_size = options_.client_send_large ?
458         sizeof(LargeRequestMessage) : sizeof(RequestMessage);
459     request.header.msgh_remote_port = RemotePort();
460     kern_return_t kr;
461     switch (options_.client_reply_port_type) {
462       case Options::kReplyPortNormal:
463         request.header.msgh_local_port = LocalPort();
464         break;
465       case Options::kReplyPortNull:
466         request.header.msgh_local_port = MACH_PORT_NULL;
467         break;
468       case Options::kReplyPortDead: {
469         // Use a newly-allocated receive right that will be destroyed when this
470         // method returns. A send right will be made from this receive right and
471         // carried in the request message to the server. By the time the server
472         // looks at the right, it will have become a dead name.
473         local_receive_port_owner.reset(NewMachPort(MACH_PORT_RIGHT_RECEIVE));
474         ASSERT_TRUE(local_receive_port_owner.is_valid());
475         request.header.msgh_local_port = local_receive_port_owner.get();
476         break;
477       }
478     }
479     request.header.msgh_id = kRequestMessageID;
480     if (options_.client_send_complex) {
481       // Allocate a new receive right in this process and make a send right that
482       // will appear in the parent process. This is used to test that the server
483       // properly handles ownership of resources received in complex messages.
484       request.body.msgh_descriptor_count = 1;
485       child_complex_message_port_.reset(NewMachPort(MACH_PORT_RIGHT_RECEIVE));
486       ASSERT_TRUE(child_complex_message_port_.is_valid());
487       request.port_descriptor.name = child_complex_message_port_.get();
488       request.port_descriptor.disposition = MACH_MSG_TYPE_MAKE_SEND;
489       request.port_descriptor.type = MACH_MSG_PORT_DESCRIPTOR;
490     } else {
491       request.body.msgh_descriptor_count = 0;
492       request.port_descriptor.name = MACH_PORT_NULL;
493       request.port_descriptor.disposition = 0;
494       request.port_descriptor.type = 0;
495     }
496     request.ndr = NDR_record;
497     request.number = requests_++;
498 
499     if (options_.client_send_large) {
500       memset(request.data, '!', sizeof(request.data));
501     }
502 
503     kr = mach_msg(&request.header,
504                   MACH_SEND_MSG | MACH_SEND_TIMEOUT,
505                   request.header.msgh_size,
506                   0,
507                   MACH_PORT_NULL,
508                   MACH_MSG_TIMEOUT_NONE,
509                   MACH_PORT_NULL);
510     ASSERT_EQ(kr, MACH_MSG_SUCCESS) << MachErrorMessage(kr, "mach_msg");
511   }
512 
513   // In the child process, waits for a reply message from the server.
ChildWaitForReply()514   void ChildWaitForReply() {
515     if (!options_.client_expect_reply) {
516       // The client shouldn’t expect a reply when it didn’t send a good reply
517       // port with its request, or when testing the server behaving in a way
518       // that doesn’t send replies.
519       return;
520     }
521 
522     struct ReceiveReplyMessage : public ReplyMessage {
523       mach_msg_trailer_t trailer;
524     };
525 
526     ReceiveReplyMessage reply = {};
527     kern_return_t kr = mach_msg(&reply.Head,
528                                 MACH_RCV_MSG,
529                                 0,
530                                 sizeof(reply),
531                                 LocalPort(),
532                                 MACH_MSG_TIMEOUT_NONE,
533                                 MACH_PORT_NULL);
534     ASSERT_EQ(kr, MACH_MSG_SUCCESS) << MachErrorMessage(kr, "mach_msg");
535 
536     ASSERT_EQ(reply.Head.msgh_bits,
537               implicit_cast<mach_msg_bits_t>(
538                   MACH_MSGH_BITS(0, MACH_MSG_TYPE_MOVE_SEND)));
539     ASSERT_EQ(reply.Head.msgh_size, sizeof(ReplyMessage));
540     ASSERT_EQ(reply.Head.msgh_remote_port, kMachPortNull);
541     ASSERT_EQ(reply.Head.msgh_local_port, LocalPort());
542     ASSERT_EQ(reply.Head.msgh_id, kReplyMessageID);
543     ASSERT_EQ(memcmp(&reply.NDR, &NDR_record, sizeof(NDR_record)), 0);
544     ASSERT_EQ(reply.RetCode, options_.server_mig_retcode);
545     ASSERT_EQ(reply.number, replies_);
546     ASSERT_EQ(
547         reply.trailer.msgh_trailer_type,
548         implicit_cast<mach_msg_trailer_type_t>(MACH_MSG_TRAILER_FORMAT_0));
549     ASSERT_EQ(reply.trailer.msgh_trailer_size, MACH_MSG_TRAILER_MINIMUM_SIZE);
550 
551     ++replies_;
552   }
553 
554   // For test types where the child needs to notify the server in the parent
555   // that the child is ready, this method will send a byte via the POSIX pipe.
556   // The parent will be waiting in a read() on this pipe, and will proceed to
557   // running MachMessageServer() once it’s received.
ChildNotifyParentViaPipe()558   void ChildNotifyParentViaPipe() {
559     char c = '\0';
560     CheckedWriteFile(WritePipeHandle(), &c, 1);
561   }
562 
563   // In the child process, sends a request message to the server and then
564   // receives a reply message.
ChildSendRequestAndWaitForReply()565   void ChildSendRequestAndWaitForReply() {
566     ASSERT_NO_FATAL_FAILURE(ChildSendRequest());
567 
568     if (options_.parent_wait_for_child_pipe &&
569         !options_.child_send_all_requests_before_receiving_any_replies) {
570       // The parent is waiting to read a byte to indicate that the message has
571       // been placed in the queue.
572       ASSERT_NO_FATAL_FAILURE(ChildNotifyParentViaPipe());
573     }
574 
575     ASSERT_NO_FATAL_FAILURE(ChildWaitForReply());
576   }
577 
578   const Options& options_;
579 
580   // A receive right allocated in the child process. A send right will be
581   // created from this right and sent to the parent parent process in the
582   // request message.
583   base::mac::ScopedMachReceiveRight child_complex_message_port_;
584 
585   // The send right received in the parent process. This right is stored in a
586   // member variable to test that resources carried in complex messages are
587   // properly destroyed in the server when expected.
588   mach_port_t parent_complex_message_port_;
589 
590   static uint32_t requests_;
591   static uint32_t replies_;
592 
593   static constexpr mach_msg_id_t kRequestMessageID = 16237;
594   static constexpr mach_msg_id_t kReplyMessageID = kRequestMessageID + 100;
595 
596   DISALLOW_COPY_AND_ASSIGN(TestMachMessageServer);
597 };
598 
599 uint32_t TestMachMessageServer::requests_;
600 uint32_t TestMachMessageServer::replies_;
601 constexpr mach_msg_id_t TestMachMessageServer::kRequestMessageID;
602 constexpr mach_msg_id_t TestMachMessageServer::kReplyMessageID;
603 
TEST(MachMessageServer,Basic)604 TEST(MachMessageServer, Basic) {
605   // The client sends one message to the server, which will wait indefinitely in
606   // blocking mode for it.
607   TestMachMessageServer::Options options;
608   TestMachMessageServer test_mach_message_server(options);
609   test_mach_message_server.Test();
610 }
611 
TEST(MachMessageServer,NonblockingNoMessage)612 TEST(MachMessageServer, NonblockingNoMessage) {
613   // The server waits in nonblocking mode and the client sends nothing, so the
614   // server should return immediately without processing any message.
615   TestMachMessageServer::Options options;
616   options.expect_server_interface_method_called = false;
617   options.server_timeout_ms = kMachMessageTimeoutNonblocking;
618   options.expect_server_result = MACH_RCV_TIMED_OUT;
619   options.expect_server_transaction_count = 0;
620   options.client_send_request_count = 0;
621   TestMachMessageServer test_mach_message_server(options);
622   test_mach_message_server.Test();
623 }
624 
TEST(MachMessageServer,TimeoutNoMessage)625 TEST(MachMessageServer, TimeoutNoMessage) {
626   // The server waits in blocking mode for one message, but with a timeout. The
627   // client sends no message, so the server returns after the timeout.
628   TestMachMessageServer::Options options;
629   options.expect_server_interface_method_called = false;
630   options.server_timeout_ms = 10;
631   options.expect_server_result = MACH_RCV_TIMED_OUT;
632   options.expect_server_transaction_count = 0;
633   options.client_send_request_count = 0;
634   TestMachMessageServer test_mach_message_server(options);
635   test_mach_message_server.Test();
636 }
637 
TEST(MachMessageServer,Nonblocking)638 TEST(MachMessageServer, Nonblocking) {
639   // The client sends one message to the server and then signals the server that
640   // it’s safe to start waiting for it in nonblocking mode. The message is in
641   // the server’s queue, so it’s able to receive it when it begins listening in
642   // nonblocking mode.
643   TestMachMessageServer::Options options;
644   options.parent_wait_for_child_pipe = true;
645   options.server_timeout_ms = kMachMessageTimeoutNonblocking;
646   TestMachMessageServer test_mach_message_server(options);
647   test_mach_message_server.Test();
648 }
649 
TEST(MachMessageServer,Timeout)650 TEST(MachMessageServer, Timeout) {
651   // The client sends one message to the server, which will wait in blocking
652   // mode for it up to a specific timeout.
653   TestMachMessageServer::Options options;
654   options.server_timeout_ms = 10;
655   TestMachMessageServer test_mach_message_server(options);
656   test_mach_message_server.Test();
657 }
658 
TEST(MachMessageServer,PersistentTenMessages)659 TEST(MachMessageServer, PersistentTenMessages) {
660   // The server waits for as many messages as it can receive in blocking mode
661   // with a timeout. The client sends several messages, and the server processes
662   // them all.
663   TestMachMessageServer::Options options;
664   options.server_persistent = MachMessageServer::kPersistent;
665   options.server_timeout_ms = 10;
666   options.expect_server_result = MACH_RCV_TIMED_OUT;
667   options.expect_server_transaction_count = 10;
668   options.client_send_request_count = 10;
669   TestMachMessageServer test_mach_message_server(options);
670   test_mach_message_server.Test();
671 }
672 
TEST(MachMessageServer,PersistentNonblockingFourMessages)673 TEST(MachMessageServer, PersistentNonblockingFourMessages) {
674   // The client sends several messages to the server and then signals the server
675   // that it’s safe to start waiting for them in nonblocking mode. The server
676   // then listens for them in nonblocking persistent mode, and receives all of
677   // them because they’ve been queued up. The client doesn’t wait for the
678   // replies until after it’s put all of its requests into the server’s queue.
679   //
680   // This test is sensitive to the length of the IPC queue limit. Mach ports
681   // normally have a queue length limit of MACH_PORT_QLIMIT_DEFAULT (which is
682   // MACH_PORT_QLIMIT_BASIC, or 5). The number of messages sent for this test
683   // must be below this, because the server does not begin dequeueing request
684   // messages until the client has finished sending them.
685   //
686   // The queue limit on new ports has been seen to be below
687   // MACH_PORT_QLIMIT_DEFAULT, so it will explicitly be set by
688   // mach_port_set_attributes() for this test. This needs to happen before the
689   // child is allowed to begin sending messages, so
690   // child_wait_for_parent_pipe_early is used to make the child wait until the
691   // parent is ready.
692   constexpr size_t kTransactionCount = 4;
693   static_assert(kTransactionCount <= MACH_PORT_QLIMIT_DEFAULT,
694                 "must not exceed queue limit");
695 
696   TestMachMessageServer::Options options;
697   options.parent_wait_for_child_pipe = true;
698   options.server_persistent = MachMessageServer::kPersistent;
699   options.server_timeout_ms = kMachMessageTimeoutNonblocking;
700   options.expect_server_result = MACH_RCV_TIMED_OUT;
701   options.expect_server_transaction_count = kTransactionCount;
702   options.child_wait_for_parent_pipe_early = true;
703   options.client_send_request_count = kTransactionCount;
704   options.child_send_all_requests_before_receiving_any_replies = true;
705   TestMachMessageServer test_mach_message_server(options);
706   test_mach_message_server.Test();
707 }
708 
TEST(MachMessageServer,ReturnCodeInvalidArgument)709 TEST(MachMessageServer, ReturnCodeInvalidArgument) {
710   // This tests that the mig_reply_error_t::RetCode field is properly returned
711   // to the client.
712   TestMachMessageServer::Options options;
713   options.server_mig_retcode = KERN_INVALID_ARGUMENT;
714   TestMachMessageServer test_mach_message_server(options);
715   test_mach_message_server.Test();
716 }
717 
TEST(MachMessageServer,ReturnCodeNoReply)718 TEST(MachMessageServer, ReturnCodeNoReply) {
719   // This tests that when mig_reply_error_t::RetCode is set to MIG_NO_REPLY, no
720   // response is sent to the client.
721   TestMachMessageServer::Options options;
722   options.server_mig_retcode = MIG_NO_REPLY;
723   options.client_expect_reply = false;
724   options.child_wait_for_parent_pipe_late = true;
725   TestMachMessageServer test_mach_message_server(options);
726   test_mach_message_server.Test();
727 }
728 
TEST(MachMessageServer,ReplyPortNull)729 TEST(MachMessageServer, ReplyPortNull) {
730   // The client sets its reply port to MACH_PORT_NULL. The server should see
731   // this and avoid sending a message to the null port. No reply message is
732   // sent and the server returns success.
733   TestMachMessageServer::Options options;
734   options.client_reply_port_type =
735       TestMachMessageServer::Options::kReplyPortNull;
736   options.client_expect_reply = false;
737   TestMachMessageServer test_mach_message_server(options);
738   test_mach_message_server.Test();
739 }
740 
TEST(MachMessageServer,ReplyPortDead)741 TEST(MachMessageServer, ReplyPortDead) {
742   // The client allocates a new port and uses it as the reply port in its
743   // request message, and then deallocates its receive right to that port. It
744   // then signals the server to process the request message. The server’s view
745   // of the port is that it is a dead name. The server function will return
746   // MACH_SEND_INVALID_DEST because it’s not possible to send a message to a
747   // dead name.
748   TestMachMessageServer::Options options;
749   options.parent_wait_for_child_pipe = true;
750   options.expect_server_result = MACH_SEND_INVALID_DEST;
751   options.client_reply_port_type =
752       TestMachMessageServer::Options::kReplyPortDead;
753   options.client_expect_reply = false;
754   TestMachMessageServer test_mach_message_server(options);
755   test_mach_message_server.Test();
756 }
757 
TEST(MachMessageServer,Complex)758 TEST(MachMessageServer, Complex) {
759   // The client allocates a new receive right and sends a complex request
760   // message to the server with a send right made out of this receive right. The
761   // server receives this message and is instructed to destroy the send right
762   // when it is done handling the request-reply transaction. The former send
763   // right is verified to be invalid after the server runs. This test ensures
764   // that resources transferred to a server process temporarily aren’t leaked.
765   TestMachMessageServer::Options options;
766   options.client_send_complex = true;
767   TestMachMessageServer test_mach_message_server(options);
768   test_mach_message_server.Test();
769 }
770 
TEST(MachMessageServer,ComplexNotDestroyed)771 TEST(MachMessageServer, ComplexNotDestroyed) {
772   // As in MachMessageServer.Complex, but the server is instructed not to
773   // destroy the send right. After the server runs, the send right is verified
774   // to continue to exist in the server task. The client process is then
775   // signalled by pipe that it’s safe to exit so that the send right in the
776   // server task doesn’t prematurely become a dead name. This test ensures that
777   // rights that are expected to be retained in the server task are properly
778   // retained.
779   TestMachMessageServer::Options options;
780   options.server_destroy_complex = false;
781   options.expect_server_destroyed_complex = false;
782   options.client_send_complex = true;
783   TestMachMessageServer test_mach_message_server(options);
784   test_mach_message_server.Test();
785 }
786 
TEST(MachMessageServer,ComplexDestroyedInvalidArgument)787 TEST(MachMessageServer, ComplexDestroyedInvalidArgument) {
788   // As in MachMessageServer.ComplexNotDestroyed, but the server does not return
789   // a successful code via MIG. The server is expected to destroy resources in
790   // this case, because server_destroy_complex = false is only honored when a
791   // MIG request is handled successfully or with no reply.
792   TestMachMessageServer::Options options;
793   options.server_mig_retcode = KERN_INVALID_TASK;
794   options.server_destroy_complex = false;
795   options.client_send_complex = true;
796   TestMachMessageServer test_mach_message_server(options);
797   test_mach_message_server.Test();
798 }
799 
TEST(MachMessageServer,ComplexNotDestroyedNoReply)800 TEST(MachMessageServer, ComplexNotDestroyedNoReply) {
801   // As in MachMessageServer.ComplexNotDestroyed, but the server does not send
802   // a reply message and is expected to retain the send right in the server
803   // task.
804   TestMachMessageServer::Options options;
805   options.server_mig_retcode = MIG_NO_REPLY;
806   options.server_destroy_complex = false;
807   options.expect_server_destroyed_complex = false;
808   options.client_send_complex = true;
809   options.client_expect_reply = false;
810   options.child_wait_for_parent_pipe_late = true;
811   TestMachMessageServer test_mach_message_server(options);
812   test_mach_message_server.Test();
813 }
814 
TEST(MachMessageServer,ReceiveLargeError)815 TEST(MachMessageServer, ReceiveLargeError) {
816   // The client sends a request to the server that is larger than the server is
817   // expecting. server_receive_large is kReceiveLargeError, so the request is
818   // destroyed and the server returns a MACH_RCV_TOO_LARGE error. The client
819   // does not receive a reply.
820   TestMachMessageServer::Options options;
821   options.expect_server_result = MACH_RCV_TOO_LARGE;
822   options.expect_server_transaction_count = 0;
823   options.client_send_large = true;
824   options.client_expect_reply = false;
825   TestMachMessageServer test_mach_message_server(options);
826   test_mach_message_server.Test();
827 }
828 
TEST(MachMessageServer,ReceiveLargeRetry)829 TEST(MachMessageServer, ReceiveLargeRetry) {
830   // The client sends a request to the server that is larger than the server is
831   // initially expecting. server_receive_large is kReceiveLargeResize, so a new
832   // buffer is allocated to receive the message. The server receives the large
833   // request message, processes it, and returns a reply to the client.
834   TestMachMessageServer::Options options;
835   options.server_receive_large = MachMessageServer::kReceiveLargeResize;
836   options.client_send_large = true;
837   TestMachMessageServer test_mach_message_server(options);
838   test_mach_message_server.Test();
839 }
840 
TEST(MachMessageServer,ReceiveLargeIgnore)841 TEST(MachMessageServer, ReceiveLargeIgnore) {
842   // The client sends a request to the server that is larger than the server is
843   // expecting. server_receive_large is kReceiveLargeIgnore, so the request is
844   // destroyed but the server does not consider this an error. The server is
845   // running in blocking mode with a timeout, and continues to wait for a
846   // message until it times out. The client does not receive a reply.
847   TestMachMessageServer::Options options;
848   options.server_receive_large = MachMessageServer::kReceiveLargeIgnore;
849   options.server_timeout_ms = 10;
850   options.expect_server_result = MACH_RCV_TIMED_OUT;
851   options.expect_server_transaction_count = 0;
852   options.client_send_large = true;
853   options.client_expect_reply = false;
854   TestMachMessageServer test_mach_message_server(options);
855   test_mach_message_server.Test();
856 }
857 
858 }  // namespace
859 }  // namespace test
860 }  // namespace crashpad
861