• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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