Home | History | Annotate | Download | only in mac
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "sandbox/mac/bootstrap_sandbox.h"
      6 
      7 #include <CoreFoundation/CoreFoundation.h>
      8 #import <Foundation/Foundation.h>
      9 #include <mach/mach.h>
     10 #include <servers/bootstrap.h>
     11 
     12 #include "base/logging.h"
     13 #include "base/mac/mac_util.h"
     14 #include "base/mac/mach_logging.h"
     15 #include "base/mac/scoped_nsobject.h"
     16 #include "base/mac/scoped_mach_port.h"
     17 #include "base/process/kill.h"
     18 #include "base/strings/stringprintf.h"
     19 #include "base/test/multiprocess_test.h"
     20 #include "base/test/test_timeouts.h"
     21 #import "testing/gtest_mac.h"
     22 #include "testing/multiprocess_func_list.h"
     23 
     24 NSString* const kTestNotification = @"org.chromium.bootstrap_sandbox_test";
     25 
     26 @interface DistributedNotificationObserver : NSObject {
     27  @private
     28   int receivedCount_;
     29   base::scoped_nsobject<NSString> object_;
     30 }
     31 - (int)receivedCount;
     32 - (NSString*)object;
     33 - (void)waitForNotification;
     34 @end
     35 
     36 @implementation DistributedNotificationObserver
     37 - (id)init {
     38   if ((self = [super init])) {
     39     [[NSDistributedNotificationCenter defaultCenter]
     40         addObserver:self
     41            selector:@selector(observeNotification:)
     42                name:kTestNotification
     43              object:nil];
     44   }
     45   return self;
     46 }
     47 
     48 - (void)dealloc {
     49   [[NSDistributedNotificationCenter defaultCenter]
     50       removeObserver:self
     51                 name:kTestNotification
     52               object:nil];
     53   [super dealloc];
     54 }
     55 
     56 - (int)receivedCount {
     57   return receivedCount_;
     58 }
     59 
     60 - (NSString*)object {
     61   return object_.get();
     62 }
     63 
     64 - (void)waitForNotification {
     65   object_.reset();
     66   CFRunLoopRunInMode(kCFRunLoopDefaultMode,
     67       TestTimeouts::action_timeout().InSeconds(), false);
     68 }
     69 
     70 - (void)observeNotification:(NSNotification*)notification {
     71   ++receivedCount_;
     72   object_.reset([[notification object] copy]);
     73   CFRunLoopStop(CFRunLoopGetCurrent());
     74 }
     75 @end
     76 
     77 ////////////////////////////////////////////////////////////////////////////////
     78 
     79 namespace sandbox {
     80 
     81 class BootstrapSandboxTest : public base::MultiProcessTest {
     82  public:
     83   virtual void SetUp() OVERRIDE {
     84     base::MultiProcessTest::SetUp();
     85 
     86     sandbox_ = BootstrapSandbox::Create();
     87     ASSERT_TRUE(sandbox_.get());
     88   }
     89 
     90   BootstrapSandboxPolicy BaselinePolicy() {
     91     BootstrapSandboxPolicy policy;
     92     if (base::mac::IsOSSnowLeopard())
     93       policy.rules["com.apple.SecurityServer"] = Rule(POLICY_ALLOW);
     94     return policy;
     95   }
     96 
     97   void RunChildWithPolicy(int policy_id,
     98                           const char* child_name,
     99                           base::ProcessHandle* out_pid) {
    100     sandbox_->PrepareToForkWithPolicy(policy_id);
    101     base::LaunchOptions options;
    102     options.replacement_bootstrap_name = sandbox_->server_bootstrap_name();
    103     base::ProcessHandle pid = SpawnChildWithOptions(child_name, options);
    104     ASSERT_GT(pid, 0);
    105     sandbox_->FinishedFork(pid);
    106     int code = 0;
    107     EXPECT_TRUE(base::WaitForExitCode(pid, &code));
    108     EXPECT_EQ(0, code);
    109     if (out_pid)
    110       *out_pid = pid;
    111   }
    112 
    113  protected:
    114   scoped_ptr<BootstrapSandbox> sandbox_;
    115 };
    116 
    117 const char kNotificationTestMain[] = "PostNotification";
    118 
    119 // Run the test without the sandbox.
    120 TEST_F(BootstrapSandboxTest, DistributedNotifications_Unsandboxed) {
    121   base::scoped_nsobject<DistributedNotificationObserver> observer(
    122       [[DistributedNotificationObserver alloc] init]);
    123 
    124   base::ProcessHandle pid = SpawnChild(kNotificationTestMain);
    125   ASSERT_GT(pid, 0);
    126   int code = 0;
    127   EXPECT_TRUE(base::WaitForExitCode(pid, &code));
    128   EXPECT_EQ(0, code);
    129 
    130   [observer waitForNotification];
    131   EXPECT_EQ(1, [observer receivedCount]);
    132   EXPECT_EQ(pid, [[observer object] intValue]);
    133 }
    134 
    135 // Run the test with the sandbox enabled without notifications on the policy
    136 // whitelist.
    137 TEST_F(BootstrapSandboxTest, DistributedNotifications_SandboxDeny) {
    138   base::scoped_nsobject<DistributedNotificationObserver> observer(
    139       [[DistributedNotificationObserver alloc] init]);
    140 
    141   sandbox_->RegisterSandboxPolicy(1, BaselinePolicy());
    142   RunChildWithPolicy(1, kNotificationTestMain, NULL);
    143 
    144   [observer waitForNotification];
    145   EXPECT_EQ(0, [observer receivedCount]);
    146   EXPECT_EQ(nil, [observer object]);
    147 }
    148 
    149 // Run the test with notifications permitted.
    150 TEST_F(BootstrapSandboxTest, DistributedNotifications_SandboxAllow) {
    151   base::scoped_nsobject<DistributedNotificationObserver> observer(
    152       [[DistributedNotificationObserver alloc] init]);
    153 
    154   BootstrapSandboxPolicy policy(BaselinePolicy());
    155   // 10.9:
    156   policy.rules["com.apple.distributed_notifications@Uv3"] = Rule(POLICY_ALLOW);
    157   policy.rules["com.apple.distributed_notifications@1v3"] = Rule(POLICY_ALLOW);
    158   // 10.6:
    159   policy.rules["com.apple.system.notification_center"] = Rule(POLICY_ALLOW);
    160   policy.rules["com.apple.distributed_notifications.2"] = Rule(POLICY_ALLOW);
    161   sandbox_->RegisterSandboxPolicy(2, policy);
    162 
    163   base::ProcessHandle pid;
    164   RunChildWithPolicy(2, kNotificationTestMain, &pid);
    165 
    166   [observer waitForNotification];
    167   EXPECT_EQ(1, [observer receivedCount]);
    168   EXPECT_EQ(pid, [[observer object] intValue]);
    169 }
    170 
    171 MULTIPROCESS_TEST_MAIN(PostNotification) {
    172   [[NSDistributedNotificationCenter defaultCenter]
    173       postNotificationName:kTestNotification
    174                     object:[NSString stringWithFormat:@"%d", getpid()]];
    175   return 0;
    176 }
    177 
    178 const char kTestServer[] = "org.chromium.test_bootstrap_server";
    179 
    180 TEST_F(BootstrapSandboxTest, PolicyDenyError) {
    181   BootstrapSandboxPolicy policy(BaselinePolicy());
    182   policy.rules[kTestServer] = Rule(POLICY_DENY_ERROR);
    183   sandbox_->RegisterSandboxPolicy(1, policy);
    184 
    185   RunChildWithPolicy(1, "PolicyDenyError", NULL);
    186 }
    187 
    188 MULTIPROCESS_TEST_MAIN(PolicyDenyError) {
    189   mach_port_t port = MACH_PORT_NULL;
    190   kern_return_t kr = bootstrap_look_up(bootstrap_port, kTestServer,
    191       &port);
    192   CHECK_EQ(BOOTSTRAP_UNKNOWN_SERVICE, kr);
    193   CHECK(port == MACH_PORT_NULL);
    194 
    195   kr = bootstrap_look_up(bootstrap_port, "org.chromium.some_other_server",
    196       &port);
    197   CHECK_EQ(BOOTSTRAP_UNKNOWN_SERVICE, kr);
    198   CHECK(port == MACH_PORT_NULL);
    199 
    200   return 0;
    201 }
    202 
    203 TEST_F(BootstrapSandboxTest, PolicyDenyDummyPort) {
    204   BootstrapSandboxPolicy policy(BaselinePolicy());
    205   policy.rules[kTestServer] = Rule(POLICY_DENY_DUMMY_PORT);
    206   sandbox_->RegisterSandboxPolicy(1, policy);
    207 
    208   RunChildWithPolicy(1, "PolicyDenyDummyPort", NULL);
    209 }
    210 
    211 MULTIPROCESS_TEST_MAIN(PolicyDenyDummyPort) {
    212   mach_port_t port = MACH_PORT_NULL;
    213   kern_return_t kr = bootstrap_look_up(bootstrap_port, kTestServer,
    214       &port);
    215   CHECK_EQ(KERN_SUCCESS, kr);
    216   CHECK(port != MACH_PORT_NULL);
    217   return 0;
    218 }
    219 
    220 struct SubstitutePortAckSend {
    221   mach_msg_header_t header;
    222   char buf[32];
    223 };
    224 
    225 struct SubstitutePortAckRecv : public SubstitutePortAckSend {
    226   mach_msg_trailer_t trailer;
    227 };
    228 
    229 const char kSubstituteAck[] = "Hello, this is doge!";
    230 
    231 TEST_F(BootstrapSandboxTest, PolicySubstitutePort) {
    232   mach_port_t task = mach_task_self();
    233 
    234   mach_port_t port;
    235   ASSERT_EQ(KERN_SUCCESS, mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE,
    236       &port));
    237   base::mac::ScopedMachReceiveRight scoped_port(port);
    238 
    239   mach_port_urefs_t send_rights = 0;
    240   ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
    241       &send_rights));
    242   EXPECT_EQ(0u, send_rights);
    243 
    244   ASSERT_EQ(KERN_SUCCESS, mach_port_insert_right(task, port, port,
    245       MACH_MSG_TYPE_MAKE_SEND));
    246   base::mac::ScopedMachSendRight scoped_port_send(port);
    247 
    248   send_rights = 0;
    249   ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
    250       &send_rights));
    251   EXPECT_EQ(1u, send_rights);
    252 
    253   BootstrapSandboxPolicy policy(BaselinePolicy());
    254   policy.rules[kTestServer] = Rule(port);
    255   sandbox_->RegisterSandboxPolicy(1, policy);
    256 
    257   RunChildWithPolicy(1, "PolicySubstitutePort", NULL);
    258 
    259   struct SubstitutePortAckRecv msg;
    260   bzero(&msg, sizeof(msg));
    261   msg.header.msgh_size = sizeof(msg);
    262   msg.header.msgh_local_port = port;
    263   kern_return_t kr = mach_msg(&msg.header, MACH_RCV_MSG, 0,
    264       msg.header.msgh_size, port,
    265       TestTimeouts::tiny_timeout().InMilliseconds(), MACH_PORT_NULL);
    266   EXPECT_EQ(KERN_SUCCESS, kr);
    267 
    268   send_rights = 0;
    269   ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
    270       &send_rights));
    271   EXPECT_EQ(1u, send_rights);
    272 
    273   EXPECT_EQ(0, strncmp(kSubstituteAck, msg.buf, sizeof(msg.buf)));
    274 }
    275 
    276 MULTIPROCESS_TEST_MAIN(PolicySubstitutePort) {
    277   mach_port_t port = MACH_PORT_NULL;
    278   kern_return_t kr = bootstrap_look_up(bootstrap_port, kTestServer, &port);
    279   CHECK_EQ(KERN_SUCCESS, kr);
    280   CHECK(port != MACH_PORT_NULL);
    281 
    282   struct SubstitutePortAckSend msg;
    283   bzero(&msg, sizeof(msg));
    284   msg.header.msgh_size = sizeof(msg);
    285   msg.header.msgh_remote_port = port;
    286   msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MOVE_SEND);
    287   strncpy(msg.buf, kSubstituteAck, sizeof(msg.buf));
    288 
    289   CHECK_EQ(KERN_SUCCESS, mach_msg_send(&msg.header));
    290 
    291   return 0;
    292 }
    293 
    294 TEST_F(BootstrapSandboxTest, ForwardMessageInProcess) {
    295   mach_port_t task = mach_task_self();
    296 
    297   mach_port_t port;
    298   ASSERT_EQ(KERN_SUCCESS, mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE,
    299       &port));
    300   base::mac::ScopedMachReceiveRight scoped_port_recv(port);
    301 
    302   mach_port_urefs_t send_rights = 0;
    303   ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
    304       &send_rights));
    305   EXPECT_EQ(0u, send_rights);
    306 
    307   ASSERT_EQ(KERN_SUCCESS, mach_port_insert_right(task, port, port,
    308       MACH_MSG_TYPE_MAKE_SEND));
    309   base::mac::ScopedMachSendRight scoped_port_send(port);
    310 
    311   send_rights = 0;
    312   ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
    313       &send_rights));
    314   EXPECT_EQ(1u, send_rights);
    315 
    316   mach_port_t bp;
    317   ASSERT_EQ(KERN_SUCCESS, task_get_bootstrap_port(task, &bp));
    318   base::mac::ScopedMachSendRight scoped_bp(bp);
    319 
    320   char service_name[] = "org.chromium.sandbox.test.ForwardMessageInProcess";
    321 #pragma GCC diagnostic push
    322 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
    323   kern_return_t kr = bootstrap_register(bp, service_name, port);
    324 #pragma GCC diagnostic pop
    325   EXPECT_EQ(KERN_SUCCESS, kr);
    326 
    327   send_rights = 0;
    328   ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
    329       &send_rights));
    330   EXPECT_EQ(1u, send_rights);
    331 
    332   mach_port_t service_port;
    333   EXPECT_EQ(KERN_SUCCESS, bootstrap_look_up(bp, service_name, &service_port));
    334   base::mac::ScopedMachSendRight scoped_service_port(service_port);
    335 
    336   send_rights = 0;
    337   ASSERT_EQ(KERN_SUCCESS, mach_port_get_refs(task, port, MACH_PORT_RIGHT_SEND,
    338       &send_rights));
    339   // On 10.6, bootstrap_lookup2 may add an extra right to place it in a per-
    340   // process cache.
    341   if (base::mac::IsOSSnowLeopard())
    342     EXPECT_TRUE(send_rights == 3u || send_rights == 2u) << send_rights;
    343   else
    344     EXPECT_EQ(2u, send_rights);
    345 }
    346 
    347 const char kDefaultRuleTestAllow[] =
    348     "org.chromium.sandbox.test.DefaultRuleAllow";
    349 const char kDefaultRuleTestDeny[] =
    350     "org.chromium.sandbox.test.DefaultRuleAllow.Deny";
    351 
    352 TEST_F(BootstrapSandboxTest, DefaultRuleAllow) {
    353   mach_port_t task = mach_task_self();
    354 
    355   mach_port_t port;
    356   ASSERT_EQ(KERN_SUCCESS, mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE,
    357       &port));
    358   base::mac::ScopedMachReceiveRight scoped_port_recv(port);
    359 
    360   ASSERT_EQ(KERN_SUCCESS, mach_port_insert_right(task, port, port,
    361       MACH_MSG_TYPE_MAKE_SEND));
    362   base::mac::ScopedMachSendRight scoped_port_send(port);
    363 
    364   BootstrapSandboxPolicy policy;
    365   policy.default_rule = Rule(POLICY_ALLOW);
    366   policy.rules[kDefaultRuleTestAllow] = Rule(port);
    367   policy.rules[kDefaultRuleTestDeny] = Rule(POLICY_DENY_ERROR);
    368   sandbox_->RegisterSandboxPolicy(3, policy);
    369 
    370   base::scoped_nsobject<DistributedNotificationObserver> observer(
    371       [[DistributedNotificationObserver alloc] init]);
    372 
    373   int pid = 0;
    374   RunChildWithPolicy(3, "DefaultRuleAllow", &pid);
    375   EXPECT_GT(pid, 0);
    376 
    377   [observer waitForNotification];
    378   EXPECT_EQ(1, [observer receivedCount]);
    379   EXPECT_EQ(pid, [[observer object] intValue]);
    380 
    381   struct SubstitutePortAckRecv msg;
    382   bzero(&msg, sizeof(msg));
    383   msg.header.msgh_size = sizeof(msg);
    384   msg.header.msgh_local_port = port;
    385   kern_return_t kr = mach_msg(&msg.header, MACH_RCV_MSG, 0,
    386       msg.header.msgh_size, port,
    387       TestTimeouts::tiny_timeout().InMilliseconds(), MACH_PORT_NULL);
    388   EXPECT_EQ(KERN_SUCCESS, kr);
    389 
    390   EXPECT_EQ(0, strncmp(kSubstituteAck, msg.buf, sizeof(msg.buf)));
    391 }
    392 
    393 MULTIPROCESS_TEST_MAIN(DefaultRuleAllow) {
    394   [[NSDistributedNotificationCenter defaultCenter]
    395       postNotificationName:kTestNotification
    396                     object:[NSString stringWithFormat:@"%d", getpid()]];
    397 
    398   mach_port_t port = MACH_PORT_NULL;
    399   CHECK_EQ(BOOTSTRAP_UNKNOWN_SERVICE, bootstrap_look_up(bootstrap_port,
    400       const_cast<char*>(kDefaultRuleTestDeny), &port));
    401   CHECK(port == MACH_PORT_NULL);
    402 
    403   CHECK_EQ(KERN_SUCCESS, bootstrap_look_up(bootstrap_port,
    404       const_cast<char*>(kDefaultRuleTestAllow), &port));
    405   CHECK(port != MACH_PORT_NULL);
    406 
    407   struct SubstitutePortAckSend msg;
    408   bzero(&msg, sizeof(msg));
    409   msg.header.msgh_size = sizeof(msg);
    410   msg.header.msgh_remote_port = port;
    411   msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MOVE_SEND);
    412   strncpy(msg.buf, kSubstituteAck, sizeof(msg.buf));
    413 
    414   CHECK_EQ(KERN_SUCCESS, mach_msg_send(&msg.header));
    415 
    416   return 0;
    417 }
    418 
    419 TEST_F(BootstrapSandboxTest, ChildOutliveSandbox) {
    420   const int kTestPolicyId = 1;
    421   mach_port_t task = mach_task_self();
    422 
    423   // Create a server port.
    424   mach_port_t port;
    425   ASSERT_EQ(KERN_SUCCESS, mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE,
    426       &port));
    427   base::mac::ScopedMachReceiveRight scoped_port_recv(port);
    428 
    429   ASSERT_EQ(KERN_SUCCESS, mach_port_insert_right(task, port, port,
    430       MACH_MSG_TYPE_MAKE_SEND));
    431   base::mac::ScopedMachSendRight scoped_port_send(port);
    432 
    433   // Set up the policy and register the port.
    434   BootstrapSandboxPolicy policy(BaselinePolicy());
    435   policy.rules["sync"] = Rule(port);
    436   sandbox_->RegisterSandboxPolicy(kTestPolicyId, policy);
    437 
    438   // Launch the child.
    439   sandbox_->PrepareToForkWithPolicy(kTestPolicyId);
    440   base::LaunchOptions options;
    441   options.replacement_bootstrap_name = sandbox_->server_bootstrap_name();
    442   base::ProcessHandle pid =
    443       SpawnChildWithOptions("ChildOutliveSandbox", options);
    444   ASSERT_GT(pid, 0);
    445   sandbox_->FinishedFork(pid);
    446 
    447   // Synchronize with the child.
    448   mach_msg_empty_rcv_t rcv_msg;
    449   bzero(&rcv_msg, sizeof(rcv_msg));
    450   kern_return_t kr = mach_msg(&rcv_msg.header, MACH_RCV_MSG, 0,
    451       sizeof(rcv_msg), port,
    452       TestTimeouts::tiny_timeout().InMilliseconds(), MACH_PORT_NULL);
    453   ASSERT_EQ(KERN_SUCCESS, kr) << mach_error_string(kr);
    454 
    455   // Destroy the sandbox.
    456   sandbox_.reset();
    457 
    458   // Synchronize again with the child.
    459   mach_msg_empty_send_t send_msg;
    460   bzero(&send_msg, sizeof(send_msg));
    461   send_msg.header.msgh_size = sizeof(send_msg);
    462   send_msg.header.msgh_remote_port = rcv_msg.header.msgh_remote_port;
    463   send_msg.header.msgh_bits =
    464       MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MOVE_SEND_ONCE);
    465   kr = mach_msg(&send_msg.header, MACH_SEND_MSG, send_msg.header.msgh_size, 0,
    466       MACH_PORT_NULL, TestTimeouts::tiny_timeout().InMilliseconds(),
    467       MACH_PORT_NULL);
    468   EXPECT_EQ(KERN_SUCCESS, kr) << mach_error_string(kr);
    469 
    470   int code = 0;
    471   EXPECT_TRUE(base::WaitForExitCode(pid, &code));
    472   EXPECT_EQ(0, code);
    473 }
    474 
    475 MULTIPROCESS_TEST_MAIN(ChildOutliveSandbox) {
    476   // Get the synchronization channel.
    477   mach_port_t port = MACH_PORT_NULL;
    478   CHECK_EQ(KERN_SUCCESS, bootstrap_look_up(bootstrap_port, "sync", &port));
    479 
    480   // Create a reply port.
    481   mach_port_t reply_port;
    482   CHECK_EQ(KERN_SUCCESS, mach_port_allocate(mach_task_self(),
    483       MACH_PORT_RIGHT_RECEIVE, &reply_port));
    484   base::mac::ScopedMachReceiveRight scoped_reply_port(reply_port);
    485 
    486   // Send a message to shutdown the sandbox.
    487   mach_msg_empty_send_t send_msg;
    488   bzero(&send_msg, sizeof(send_msg));
    489   send_msg.header.msgh_size = sizeof(send_msg);
    490   send_msg.header.msgh_local_port = reply_port;
    491   send_msg.header.msgh_remote_port = port;
    492   send_msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND,
    493                                              MACH_MSG_TYPE_MAKE_SEND_ONCE);
    494   kern_return_t kr = mach_msg_send(&send_msg.header);
    495   MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_msg_send";
    496 
    497   // Flood the server's message queue with messages. There should be some
    498   // pending when the sandbox is destroyed.
    499   for (int i = 0; i < 20; ++i) {
    500     mach_port_t tmp = MACH_PORT_NULL;
    501     std::string name = base::StringPrintf("test.%d", i);
    502     bootstrap_look_up(bootstrap_port, const_cast<char*>(name.c_str()), &tmp);
    503   }
    504 
    505   // Ack that the sandbox has been shutdown.
    506   mach_msg_empty_rcv_t rcv_msg;
    507   bzero(&rcv_msg, sizeof(rcv_msg));
    508   rcv_msg.header.msgh_size = sizeof(rcv_msg);
    509   rcv_msg.header.msgh_local_port = reply_port;
    510   kr = mach_msg_receive(&rcv_msg.header);
    511   MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_msg_receive";
    512 
    513   // Try to message the sandbox.
    514   bootstrap_look_up(bootstrap_port, "test", &port);
    515 
    516   return 0;
    517 }
    518 
    519 }  // namespace sandbox
    520