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