• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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 "components/nacl/loader/nacl_ipc_adapter.h"
6 
7 #include <string.h>
8 
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "base/threading/platform_thread.h"
13 #include "base/threading/simple_thread.h"
14 #include "ipc/ipc_test_sink.h"
15 #include "native_client/src/trusted/desc/nacl_desc_custom.h"
16 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
17 #include "ppapi/c/ppb_file_io.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 
20 namespace {
21 
22 class NaClIPCAdapterTest : public testing::Test {
23  public:
NaClIPCAdapterTest()24   NaClIPCAdapterTest() {}
25 
26   // testing::Test implementation.
SetUp()27   virtual void SetUp() OVERRIDE {
28     sink_ = new IPC::TestSink;
29 
30     // Takes ownership of the sink_ pointer. Note we provide the current message
31     // loop instead of using a real IO thread. This should work OK since we do
32     // not need real IPC for the tests.
33     adapter_ = new NaClIPCAdapter(scoped_ptr<IPC::Channel>(sink_),
34                                   base::MessageLoopProxy::current().get());
35   }
TearDown()36   virtual void TearDown() OVERRIDE {
37     sink_ = NULL;  // This pointer is actually owned by the IPCAdapter.
38     adapter_ = NULL;
39     // The adapter destructor has to post a task to destroy the Channel on the
40     // IO thread. For the purposes of the test, we just need to make sure that
41     // task gets run, or it will appear as a leak.
42     message_loop_.RunUntilIdle();
43   }
44 
45  protected:
BlockingReceive(void * buf,size_t buf_size)46   int BlockingReceive(void* buf, size_t buf_size) {
47     NaClImcMsgIoVec iov = {buf, buf_size};
48     NaClImcTypedMsgHdr msg = {&iov, 1};
49     return adapter_->BlockingReceive(&msg);
50   }
51 
Send(void * buf,size_t buf_size)52   int Send(void* buf, size_t buf_size) {
53     NaClImcMsgIoVec iov = {buf, buf_size};
54     NaClImcTypedMsgHdr msg = {&iov, 1};
55     return adapter_->Send(&msg);
56   }
57 
58   base::MessageLoop message_loop_;
59 
60   scoped_refptr<NaClIPCAdapter> adapter_;
61 
62   // Messages sent from nacl to the adapter end up here. Note that we create
63   // this pointer and pass ownership of it to the IPC adapter, who will keep
64   // it alive as long as the adapter is alive. This means that when the
65   // adapter goes away, this pointer will become invalid.
66   //
67   // In real life the adapter needs to take ownership so the channel can be
68   // destroyed on the right thread.
69   IPC::TestSink* sink_;
70 };
71 
72 }  // namespace
73 
74 // Tests a simple message getting rewritten sent from native code to NaCl.
TEST_F(NaClIPCAdapterTest,SimpleReceiveRewriting)75 TEST_F(NaClIPCAdapterTest, SimpleReceiveRewriting) {
76   int routing_id = 0x89898989;
77   uint32 type = 0x55555555;
78   IPC::Message input(routing_id, type, IPC::Message::PRIORITY_NORMAL);
79   uint32 flags = input.flags();
80 
81   int value = 0x12345678;
82   input.WriteInt(value);
83   adapter_->OnMessageReceived(input);
84 
85   // Buffer just need to be big enough for our message with one int.
86   const int kBufSize = 64;
87   char buf[kBufSize];
88 
89   int bytes_read = BlockingReceive(buf, kBufSize);
90   EXPECT_EQ(sizeof(NaClIPCAdapter::NaClMessageHeader) + sizeof(int),
91             static_cast<size_t>(bytes_read));
92 
93   const NaClIPCAdapter::NaClMessageHeader* output_header =
94       reinterpret_cast<const NaClIPCAdapter::NaClMessageHeader*>(buf);
95   EXPECT_EQ(sizeof(int), output_header->payload_size);
96   EXPECT_EQ(routing_id, output_header->routing);
97   EXPECT_EQ(type, output_header->type);
98   EXPECT_EQ(flags, output_header->flags);
99   EXPECT_EQ(0u, output_header->num_fds);
100   EXPECT_EQ(0u, output_header->pad);
101 
102   // Validate the payload.
103   EXPECT_EQ(value,
104             *reinterpret_cast<const int*>(&buf[
105                 sizeof(NaClIPCAdapter::NaClMessageHeader)]));
106 }
107 
108 // Tests a simple message getting rewritten sent from NaCl to native code.
TEST_F(NaClIPCAdapterTest,SendRewriting)109 TEST_F(NaClIPCAdapterTest, SendRewriting) {
110   int routing_id = 0x89898989;
111   uint32 type = 0x55555555;
112   int value = 0x12345678;
113 
114   // Send a message with one int inside it.
115   const int buf_size = sizeof(NaClIPCAdapter::NaClMessageHeader) + sizeof(int);
116   char buf[buf_size] = {0};
117 
118   NaClIPCAdapter::NaClMessageHeader* header =
119       reinterpret_cast<NaClIPCAdapter::NaClMessageHeader*>(buf);
120   header->payload_size = sizeof(int);
121   header->routing = routing_id;
122   header->type = type;
123   header->flags = 0;
124   header->num_fds = 0;
125   *reinterpret_cast<int*>(
126       &buf[sizeof(NaClIPCAdapter::NaClMessageHeader)]) = value;
127 
128   int result = Send(buf, buf_size);
129   EXPECT_EQ(buf_size, result);
130 
131   // Check that the message came out the other end in the test sink
132   // (messages are posted, so we have to pump).
133   message_loop_.RunUntilIdle();
134   ASSERT_EQ(1u, sink_->message_count());
135   const IPC::Message* msg = sink_->GetMessageAt(0);
136 
137   EXPECT_EQ(sizeof(int), msg->payload_size());
138   EXPECT_EQ(header->routing, msg->routing_id());
139   EXPECT_EQ(header->type, msg->type());
140 
141   // Now test the partial send case. We should be able to break the message
142   // into two parts and it should still work.
143   sink_->ClearMessages();
144   int first_chunk_size = 7;
145   result = Send(buf, first_chunk_size);
146   EXPECT_EQ(first_chunk_size, result);
147 
148   // First partial send should not have made any messages.
149   message_loop_.RunUntilIdle();
150   ASSERT_EQ(0u, sink_->message_count());
151 
152   // Second partial send should do the same.
153   int second_chunk_size = 2;
154   result = Send(&buf[first_chunk_size], second_chunk_size);
155   EXPECT_EQ(second_chunk_size, result);
156   message_loop_.RunUntilIdle();
157   ASSERT_EQ(0u, sink_->message_count());
158 
159   // Send the rest of the message in a third chunk.
160   int third_chunk_size = buf_size - first_chunk_size - second_chunk_size;
161   result = Send(&buf[first_chunk_size + second_chunk_size],
162                           third_chunk_size);
163   EXPECT_EQ(third_chunk_size, result);
164 
165   // Last send should have generated one message.
166   message_loop_.RunUntilIdle();
167   ASSERT_EQ(1u, sink_->message_count());
168   msg = sink_->GetMessageAt(0);
169   EXPECT_EQ(sizeof(int), msg->payload_size());
170   EXPECT_EQ(header->routing, msg->routing_id());
171   EXPECT_EQ(header->type, msg->type());
172 }
173 
174 // Tests when a buffer is too small to receive the entire message.
TEST_F(NaClIPCAdapterTest,PartialReceive)175 TEST_F(NaClIPCAdapterTest, PartialReceive) {
176   int routing_id_1 = 0x89898989;
177   uint32 type_1 = 0x55555555;
178   IPC::Message input_1(routing_id_1, type_1, IPC::Message::PRIORITY_NORMAL);
179   int value_1 = 0x12121212;
180   input_1.WriteInt(value_1);
181   adapter_->OnMessageReceived(input_1);
182 
183   int routing_id_2 = 0x90909090;
184   uint32 type_2 = 0x66666666;
185   IPC::Message input_2(routing_id_2, type_2, IPC::Message::PRIORITY_NORMAL);
186   int value_2 = 0x23232323;
187   input_2.WriteInt(value_2);
188   adapter_->OnMessageReceived(input_2);
189 
190   const int kBufSize = 64;
191   char buf[kBufSize];
192 
193   // Read part of the first message.
194   int bytes_requested = 7;
195   int bytes_read = BlockingReceive(buf, bytes_requested);
196   ASSERT_EQ(bytes_requested, bytes_read);
197 
198   // Read the rest, this should give us the rest of the first message only.
199   bytes_read += BlockingReceive(&buf[bytes_requested],
200                                         kBufSize - bytes_requested);
201   EXPECT_EQ(sizeof(NaClIPCAdapter::NaClMessageHeader) + sizeof(int),
202             static_cast<size_t>(bytes_read));
203 
204   // Make sure we got the right message.
205   const NaClIPCAdapter::NaClMessageHeader* output_header =
206       reinterpret_cast<const NaClIPCAdapter::NaClMessageHeader*>(buf);
207   EXPECT_EQ(sizeof(int), output_header->payload_size);
208   EXPECT_EQ(routing_id_1, output_header->routing);
209   EXPECT_EQ(type_1, output_header->type);
210 
211   // Read the second message to make sure we went on to it.
212   bytes_read = BlockingReceive(buf, kBufSize);
213   EXPECT_EQ(sizeof(NaClIPCAdapter::NaClMessageHeader) + sizeof(int),
214             static_cast<size_t>(bytes_read));
215   output_header =
216       reinterpret_cast<const NaClIPCAdapter::NaClMessageHeader*>(buf);
217   EXPECT_EQ(sizeof(int), output_header->payload_size);
218   EXPECT_EQ(routing_id_2, output_header->routing);
219   EXPECT_EQ(type_2, output_header->type);
220 }
221 
222 // Tests sending messages that are too large. We test sends that are too
223 // small implicitly here and in the success case because in that case it
224 // succeeds and buffers the data.
TEST_F(NaClIPCAdapterTest,SendOverflow)225 TEST_F(NaClIPCAdapterTest, SendOverflow) {
226   int routing_id = 0x89898989;
227   uint32 type = 0x55555555;
228   int value = 0x12345678;
229 
230   // Make a message with one int inside it. Reserve some extra space so
231   // we can test what happens when we send too much data.
232   const int buf_size = sizeof(NaClIPCAdapter::NaClMessageHeader) + sizeof(int);
233   const int big_buf_size = buf_size + 4;
234   char buf[big_buf_size] = {0};
235 
236   NaClIPCAdapter::NaClMessageHeader* header =
237       reinterpret_cast<NaClIPCAdapter::NaClMessageHeader*>(buf);
238   header->payload_size = sizeof(int);
239   header->routing = routing_id;
240   header->type = type;
241   header->flags = 0;
242   header->num_fds = 0;
243   *reinterpret_cast<int*>(
244       &buf[sizeof(NaClIPCAdapter::NaClMessageHeader)]) = value;
245 
246   // Send too much data and make sure that the send fails.
247   int result = Send(buf, big_buf_size);
248   EXPECT_EQ(-1, result);
249   message_loop_.RunUntilIdle();
250   ASSERT_EQ(0u, sink_->message_count());
251 
252   // Send too much data in two chunks and make sure that the send fails.
253   int first_chunk_size = 7;
254   result = Send(buf, first_chunk_size);
255   EXPECT_EQ(first_chunk_size, result);
256 
257   // First partial send should not have made any messages.
258   message_loop_.RunUntilIdle();
259   ASSERT_EQ(0u, sink_->message_count());
260 
261   int second_chunk_size = big_buf_size - first_chunk_size;
262   result = Send(&buf[first_chunk_size], second_chunk_size);
263   EXPECT_EQ(-1, result);
264   message_loop_.RunUntilIdle();
265   ASSERT_EQ(0u, sink_->message_count());
266 }
267 
268 // Tests that when the IPC channel reports an error, that waiting reads are
269 // unblocked and return a -1 error code.
TEST_F(NaClIPCAdapterTest,ReadWithChannelError)270 TEST_F(NaClIPCAdapterTest, ReadWithChannelError) {
271   // Have a background thread that waits a bit and calls the channel error
272   // handler. This should wake up any waiting threads and immediately return
273   // -1. There is an inherent race condition in that we can't be sure if the
274   // other thread is actually waiting when this happens. This is OK, since the
275   // behavior (which we also explicitly test later) is to return -1 if the
276   // channel has already had an error when you start waiting.
277   class MyThread : public base::SimpleThread {
278    public:
279     explicit MyThread(NaClIPCAdapter* adapter)
280         : SimpleThread("NaClIPCAdapterThread"),
281           adapter_(adapter) {}
282     virtual void Run() OVERRIDE {
283       base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
284       adapter_->OnChannelError();
285     }
286    private:
287     scoped_refptr<NaClIPCAdapter> adapter_;
288   };
289   MyThread thread(adapter_.get());
290 
291   // IMPORTANT: do not return early from here down (including ASSERT_*) because
292   // the thread needs to joined or it will assert.
293   thread.Start();
294 
295   // Request data. This will normally (modulo races) block until data is
296   // received or there is an error, and the thread above will wake us up
297   // after 1s.
298   const int kBufSize = 64;
299   char buf[kBufSize];
300   int result = BlockingReceive(buf, kBufSize);
301   EXPECT_EQ(-1, result);
302 
303   // Test the "previously had an error" case. BlockingReceive should return
304   // immediately if there was an error.
305   result = BlockingReceive(buf, kBufSize);
306   EXPECT_EQ(-1, result);
307 
308   thread.Join();
309 }
310 
311 // Tests that TranslatePepperFileOpenFlags translates pepper read/write open
312 // flags into NaCl open flags correctly.
TEST_F(NaClIPCAdapterTest,TranslatePepperFileReadWriteOpenFlags)313 TEST_F(NaClIPCAdapterTest, TranslatePepperFileReadWriteOpenFlags) {
314   EXPECT_EQ(NACL_ABI_O_RDONLY,
315       TranslatePepperFileReadWriteOpenFlagsForTesting(PP_FILEOPENFLAG_READ));
316   EXPECT_EQ(NACL_ABI_O_WRONLY,
317       TranslatePepperFileReadWriteOpenFlagsForTesting(PP_FILEOPENFLAG_WRITE));
318   EXPECT_EQ(NACL_ABI_O_WRONLY | NACL_ABI_O_APPEND,
319       TranslatePepperFileReadWriteOpenFlagsForTesting(
320           PP_FILEOPENFLAG_APPEND));
321   EXPECT_EQ(NACL_ABI_O_RDWR,
322       TranslatePepperFileReadWriteOpenFlagsForTesting(
323           PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_WRITE));
324   EXPECT_EQ(NACL_ABI_O_WRONLY | NACL_ABI_O_APPEND,
325       TranslatePepperFileReadWriteOpenFlagsForTesting(
326           PP_FILEOPENFLAG_APPEND));
327   EXPECT_EQ(NACL_ABI_O_RDWR | NACL_ABI_O_APPEND,
328       TranslatePepperFileReadWriteOpenFlagsForTesting(
329           PP_FILEOPENFLAG_READ | PP_FILEOPENFLAG_APPEND));
330 
331   // Flags other than PP_FILEOPENFLAG_READ, PP_FILEOPENFLAG_WRITE, and
332   // PP_FILEOPENFLAG_APPEND are discarded.
333   EXPECT_EQ(NACL_ABI_O_WRONLY,
334       TranslatePepperFileReadWriteOpenFlagsForTesting(
335           PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE));
336   EXPECT_EQ(NACL_ABI_O_WRONLY,
337       TranslatePepperFileReadWriteOpenFlagsForTesting(
338           PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_TRUNCATE));
339   EXPECT_EQ(NACL_ABI_O_WRONLY,
340       TranslatePepperFileReadWriteOpenFlagsForTesting(
341           PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_EXCLUSIVE));
342 
343   // If none of PP_FILEOPENFLAG_READ, PP_FILEOPENFLAG_WRITE, and
344   // PP_FILEOPENFLAG_APPEND are set, the result should fall back to
345   // NACL_ABI_O_READONLY.
346   EXPECT_EQ(NACL_ABI_O_RDONLY,
347       TranslatePepperFileReadWriteOpenFlagsForTesting(0));
348   EXPECT_EQ(NACL_ABI_O_RDONLY,
349       TranslatePepperFileReadWriteOpenFlagsForTesting(
350           PP_FILEOPENFLAG_CREATE));
351   EXPECT_EQ(NACL_ABI_O_RDONLY,
352       TranslatePepperFileReadWriteOpenFlagsForTesting(
353           PP_FILEOPENFLAG_TRUNCATE));
354   EXPECT_EQ(NACL_ABI_O_RDONLY,
355       TranslatePepperFileReadWriteOpenFlagsForTesting(
356           PP_FILEOPENFLAG_EXCLUSIVE));
357 }
358