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