1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file.
4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "sandbox/mac/dispatch_source_mach.h"
6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <mach/mach.h>
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/logging.h"
10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/mac/scoped_mach_port.h"
11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/memory/scoped_ptr.h"
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/test/test_timeouts.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "testing/gtest/include/gtest/gtest.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace sandbox {
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass DispatchSourceMachTest : public testing::Test {
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public:
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void SetUp() OVERRIDE {
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    mach_port_t port = MACH_PORT_NULL;
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ASSERT_EQ(KERN_SUCCESS, mach_port_allocate(mach_task_self(),
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        MACH_PORT_RIGHT_RECEIVE, &port));
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    receive_right_.reset(port);
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ASSERT_EQ(KERN_SUCCESS, mach_port_insert_right(mach_task_self(), port,
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        port, MACH_MSG_TYPE_MAKE_SEND));
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    send_right_.reset(port);
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  mach_port_t port() { return receive_right_.get(); }
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void WaitForSemaphore(dispatch_semaphore_t semaphore) {
33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    dispatch_semaphore_wait(semaphore, dispatch_time(
34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        DISPATCH_TIME_NOW,
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        TestTimeouts::action_timeout().InSeconds() * NSEC_PER_SEC));
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private:
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::mac::ScopedMachReceiveRight receive_right_;
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::mac::ScopedMachSendRight send_right_;
41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch};
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
43116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(DispatchSourceMachTest, ReceiveAfterResume) {
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  dispatch_semaphore_t signal = dispatch_semaphore_create(0);
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool __block did_receive = false;
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DispatchSourceMach source("org.chromium.sandbox.test.ReceiveAfterResume",
48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      port(), ^{
49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          mach_msg_empty_rcv_t msg = {{0}};
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          msg.header.msgh_size = sizeof(msg);
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          msg.header.msgh_local_port = port();
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          mach_msg_receive(&msg.header);
53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          did_receive = true;
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          dispatch_semaphore_signal(signal);
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      });
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  mach_msg_empty_send_t msg = {{0}};
59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  msg.header.msgh_size = sizeof(msg);
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  msg.header.msgh_remote_port = port();
61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND);
62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ASSERT_EQ(KERN_SUCCESS, mach_msg_send(&msg.header));
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_FALSE(did_receive);
65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  source.Resume();
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  WaitForSemaphore(signal);
69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(did_receive);
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
73116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(DispatchSourceMachTest, NoMessagesAfterDestruction) {
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<int> count(new int(0));
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int* __block count_ptr = count.get();
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<DispatchSourceMach> source(new DispatchSourceMach(
78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      "org.chromium.sandbox.test.NoMessagesAfterDestruction",
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      port(), ^{
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          mach_msg_empty_rcv_t msg = {{0}};
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          msg.header.msgh_size = sizeof(msg);
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          msg.header.msgh_local_port = port();
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          mach_msg_receive(&msg.header);
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          LOG(INFO) << "Receieve " << *count_ptr;
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          ++(*count_ptr);
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }));
87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  source->Resume();
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  dispatch_queue_t queue =
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      dispatch_queue_create("org.chromium.sandbox.test.MessageSend", NULL);
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  dispatch_semaphore_t signal = dispatch_semaphore_create(0);
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (int i = 0; i < 30; ++i) {
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    dispatch_async(queue, ^{
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        mach_msg_empty_send_t msg = {{0}};
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        msg.header.msgh_size = sizeof(msg);
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        msg.header.msgh_remote_port = port();
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        msg.header.msgh_bits =
98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND);
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        mach_msg_send(&msg.header);
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    });
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // After sending five messages, shut down the source and taint the
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // pointer the handler dereferences. The test will crash if |count_ptr|
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // is being used after "free".
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (i == 5) {
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      scoped_ptr<DispatchSourceMach>* source_ptr = &source;
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      dispatch_async(queue, ^{
108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          source_ptr->reset();
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          count_ptr = reinterpret_cast<int*>(0xdeaddead);
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          dispatch_semaphore_signal(signal);
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      });
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  WaitForSemaphore(signal);
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  dispatch_release(queue);
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace sandbox
120