Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / native_client / tests / sel_main_chrome / sel_main_chrome_test.cc
1 /*
2  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6
7 #include <fcntl.h>
8 #include <cstring>
9
10 #if NACL_WINDOWS
11 # include <io.h>
12 #endif
13
14 #include "native_client/src/public/chrome_main.h"
15 #include "native_client/src/public/nacl_app.h"
16 #include "native_client/src/public/nacl_file_info.h"
17 #include "native_client/src/shared/platform/nacl_check.h"
18 #include "native_client/src/shared/platform/nacl_threads.h"
19 #include "native_client/src/shared/srpc/nacl_srpc.h"
20 #include "native_client/src/trusted/desc/nacl_desc_custom.h"
21 #include "native_client/src/trusted/desc/nacl_desc_file_info.h"
22 #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h"
23 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
24 #include "native_client/src/trusted/service_runtime/nacl_all_modules.h"
25 #include "native_client/src/trusted/service_runtime/nacl_config.h"
26 #include "native_client/src/trusted/service_runtime/nacl_valgrind_hooks.h"
27 #include "native_client/src/trusted/service_runtime/sel_addrspace.h"
28 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
29 #include "native_client/src/trusted/validator/validation_cache.h"
30
31 // A global variable that specifies whether the module should be loaded via
32 // SRPC. Its value is controlled by a command line flag kNoSrpcLoadModule.
33 bool g_load_module_srpc = true;
34 const char kNoSrpcLoadModule[] = "--no_srpc_load_module";
35
36 // A global variable that specifies whether or not the test should set
37 // the irt_load_optional flag in NaClChromeMainArgs.
38 bool g_irt_load_optional = false;
39 const char kIrtLoadOptional[] = "--irt_load_optional";
40
41 // A global variable that specifies whether or not to test validation
42 // caching of the main nexe.
43 bool g_test_validation_cache = false;
44 const char kTestValidationCache[] = "--test_validation_cache";
45
46 int OpenFileReadOnly(const char *filename) {
47 #if NACL_WINDOWS
48   return _open(filename, _O_RDONLY);
49 #else
50   return open(filename, O_RDONLY);
51 #endif
52 }
53
54 int32_t OpenFileHandleReadExec(const char *filename) {
55 #if NACL_WINDOWS
56   HANDLE h = CreateFileA(filename,
57                          GENERIC_READ | GENERIC_EXECUTE,
58                          FILE_SHARE_READ,
59                          NULL,
60                          OPEN_EXISTING,
61                          FILE_ATTRIBUTE_NORMAL,
62                          NULL);
63   // On Windows, valid handles are 32 bit unsigned integers so this is safe.
64   return reinterpret_cast<int32_t>(h);
65 #else
66   return open(filename, O_RDONLY);
67 #endif
68 }
69
70 // This launcher class does not actually launch a process, but we
71 // reuse SelLdrLauncherBase in order to use its helper methods.
72 class DummyLauncher : public nacl::SelLdrLauncherBase {
73  public:
74   explicit DummyLauncher(NaClHandle channel) {
75     channel_ = channel;
76   }
77
78   virtual bool Start(const char *url) {
79     UNREFERENCED_PARAMETER(url);
80     return true;
81   }
82 };
83
84 // Fake validation cache methods for testing.
85 struct TestValidationHandle {
86   uint64_t expected_token_lo;
87   uint64_t expected_token_hi;
88   int32_t expected_file_handle;
89   char *expected_file_path;
90 };
91
92 struct TestValidationQuery {
93   bool known_to_validate;
94 };
95
96 static void *TestCreateQuery(void *handle) {
97   UNREFERENCED_PARAMETER(handle);
98   return static_cast<void *>(new TestValidationQuery());
99 }
100
101 static void TestAddData(void *query, const unsigned char *data,
102                         size_t length) {
103   UNREFERENCED_PARAMETER(query);
104   UNREFERENCED_PARAMETER(data);
105   UNREFERENCED_PARAMETER(length);
106 }
107
108 static int TestQueryKnownToValidate(void *query) {
109   TestValidationQuery *s = static_cast<TestValidationQuery *>(query);
110   return s->known_to_validate;
111 }
112
113 static void TestSetKnownToValidate(void *query) {
114   TestValidationQuery *s = static_cast<TestValidationQuery *>(query);
115   s->known_to_validate = 1;
116 }
117
118 static void TestDestroyQuery(void *query) {
119   delete static_cast<TestValidationQuery *>(query);
120 }
121
122 static int TestCachingIsInexpensive(const struct NaClValidationMetadata *m) {
123   UNREFERENCED_PARAMETER(m);
124   return 1;
125 }
126
127 static int TestResolveFileToken(void *handle, struct NaClFileToken *file_token,
128                                 int32_t *fd, char **file_path,
129                                 uint32_t *file_path_length) {
130   TestValidationHandle *h = static_cast<TestValidationHandle *>(handle);
131   CHECK(h->expected_token_lo == file_token->lo);
132   CHECK(h->expected_token_hi == file_token->hi);
133   *fd = h->expected_file_handle;
134   *file_path = h->expected_file_path;
135   *file_path_length = static_cast<uint32_t>(strlen(h->expected_file_path));
136   return 1;
137 }
138
139 struct ThreadArgs {
140   NaClHandle channel;
141   NaClFileInfo file_info;
142 };
143
144 void WINAPI DummyRendererThread(void *thread_arg) {
145   struct ThreadArgs *args = (struct ThreadArgs *) thread_arg;
146
147   nacl::DescWrapperFactory desc_wrapper_factory;
148   DummyLauncher launcher(args->channel);
149   NaClSrpcChannel trusted_channel;
150   NaClSrpcChannel untrusted_channel;
151   if (g_load_module_srpc) {
152     struct NaClDesc *desc = NaClDescIoFromFileInfo(args->file_info,
153                                                    NACL_ABI_O_RDONLY);
154     CHECK(desc != NULL);
155     nacl::DescWrapper *nexe_desc =
156         desc_wrapper_factory.MakeGenericCleanup(desc);
157     CHECK(nexe_desc != NULL);
158     CHECK(launcher.SetupCommandAndLoad(&trusted_channel, nexe_desc));
159   } else {
160     CHECK(launcher.SetupCommand(&trusted_channel));
161   }
162   CHECK(launcher.StartModuleAndSetupAppChannel(&trusted_channel,
163                                                &untrusted_channel));
164 }
165
166 void ExampleDescDestroy(void *handle) {
167   UNREFERENCED_PARAMETER(handle);
168 }
169
170 ssize_t ExampleDescSendMsg(void *handle,
171                            const struct NaClImcTypedMsgHdr *msg,
172                            int flags) {
173   UNREFERENCED_PARAMETER(handle);
174   UNREFERENCED_PARAMETER(msg);
175   UNREFERENCED_PARAMETER(flags);
176
177   NaClLog(LOG_FATAL, "ExampleDescSendMsg: Not implemented\n");
178   return 0;
179 }
180
181 ssize_t ExampleDescRecvMsg(void *handle,
182                            struct NaClImcTypedMsgHdr *msg,
183                            int flags) {
184   UNREFERENCED_PARAMETER(handle);
185   UNREFERENCED_PARAMETER(msg);
186   UNREFERENCED_PARAMETER(flags);
187
188   NaClLog(LOG_FATAL, "ExampleDescRecvMsg: Not implemented\n");
189   return 0;
190 }
191
192 struct NaClDesc *MakeExampleDesc() {
193   struct NaClDescCustomFuncs funcs = NACL_DESC_CUSTOM_FUNCS_INITIALIZER;
194   funcs.Destroy = ExampleDescDestroy;
195   funcs.SendMsg = ExampleDescSendMsg;
196   funcs.RecvMsg = ExampleDescRecvMsg;
197   return NaClDescMakeCustomDesc(NULL, &funcs);
198 }
199
200 // Process commandline options and return the index where non-option
201 // commandline arguments begin. Assumes all options are in the front.
202 int NaClHandleArguments(int argc, char **argv) {
203   static const struct TestArguments {
204     const char *flag_name;
205     bool *flag_reference;
206     bool value_to_set;
207   } long_opts[] = {
208     {kNoSrpcLoadModule, &g_load_module_srpc, false},
209     {kIrtLoadOptional, &g_irt_load_optional, true},
210     {kTestValidationCache, &g_test_validation_cache, true},
211     {NULL, NULL, false}
212   };
213   int cur_arg = 1;
214   while (cur_arg < argc) {
215     int i = 0;
216     bool matched = false;
217     while (long_opts[i].flag_name != NULL) {
218       if (strcmp(long_opts[i].flag_name, argv[cur_arg]) == 0) {
219         *long_opts[i].flag_reference = long_opts[i].value_to_set;
220         ++cur_arg;
221         matched = true;
222         break;
223       }
224       ++i;
225     }
226     if (!matched) {
227       return cur_arg;
228     }
229   }
230   return cur_arg;
231 }
232
233 int main(int argc, char **argv) {
234   // Note that we deliberately do not call NaClAllModulesInit() here,
235   // in order to mimic what we expect the Chromium side to do.
236   NaClChromeMainInit();
237   struct NaClChromeMainArgs *args = NaClChromeMainArgsCreate();
238   struct NaClApp *nap = NaClAppCreate();
239   struct ThreadArgs thread_args;
240
241   NaClHandleBootstrapArgs(&argc, &argv);
242   int last_option_index = NaClHandleArguments(argc, argv);
243 #if NACL_LINUX
244   args->prereserved_sandbox_size = g_prereserved_sandbox_size;
245 #endif
246   // There should be two more arguments after parsing the optional ones.
247   if (last_option_index + 2 != argc) {
248     NaClLog(
249         LOG_FATAL,
250         "NaClHandleArguments stopped at opt %d (expected %d == argc(%d)-2\n",
251         last_option_index, argc - 2, argc);
252   }
253   const char *irt_filename = argv[last_option_index];
254   const char *nexe_filename = argv[last_option_index + 1];
255
256   NaClLog(LOG_INFO,
257           "SelMainChromeTest configuration:\n"
258           "g_load_module_srpc: %d\n"
259           "g_irt_load_optional: %d\n"
260           "g_test_validation_cache: %d\n",
261            g_load_module_srpc, g_irt_load_optional, g_test_validation_cache);
262
263   args->irt_fd = OpenFileReadOnly(irt_filename);
264   args->irt_load_optional = g_irt_load_optional;
265   CHECK(args->irt_fd >= 0);
266
267   memset(&thread_args.file_info, 0, sizeof thread_args.file_info);
268   thread_args.file_info.desc = OpenFileReadOnly(nexe_filename);
269   CHECK(thread_args.file_info.desc >= 0);
270   NaClFileNameForValgrind(nexe_filename);
271
272   NaClHandle socketpair[2];
273   CHECK(NaClSocketPair(socketpair) == 0);
274   args->imc_bootstrap_handle = socketpair[0];
275   thread_args.channel = socketpair[1];
276
277   // Check that NaClDescMakeCustomDesc() works when called in this context.
278   NaClAppSetDesc(nap, NACL_CHROME_DESC_BASE, MakeExampleDesc());
279
280   // Set up mock validation cache.
281   struct TestValidationHandle test_handle;
282   struct NaClValidationCache test_cache;
283   if (g_test_validation_cache) {
284     test_handle.expected_token_lo = 0xabcdef123456789LL;
285     test_handle.expected_token_hi = 0x101010101010101LL;
286     test_handle.expected_file_handle = OpenFileHandleReadExec(nexe_filename);
287     test_handle.expected_file_path = strdup(nexe_filename);
288     test_cache.handle = &test_handle;
289     test_cache.CreateQuery = &TestCreateQuery;
290     test_cache.AddData = &TestAddData;
291     test_cache.QueryKnownToValidate = &TestQueryKnownToValidate;
292     test_cache.SetKnownToValidate = &TestSetKnownToValidate;
293     test_cache.DestroyQuery = &TestDestroyQuery;
294     test_cache.CachingIsInexpensive = &TestCachingIsInexpensive;
295     test_cache.ResolveFileToken = &TestResolveFileToken;
296     args->validation_cache = &test_cache;
297     thread_args.file_info.file_token.lo = test_handle.expected_token_lo;
298     thread_args.file_info.file_token.hi = test_handle.expected_token_hi;
299   }
300   if (!g_load_module_srpc) {
301     NaClFileInfo info;
302     info.desc = OpenFileHandleReadExec(nexe_filename);
303 #if NACL_WINDOWS
304     info.desc = _open_osfhandle(info.desc, _O_RDONLY | _O_BINARY);
305 #endif
306     if (g_test_validation_cache) {
307       info.file_token.lo = test_handle.expected_token_lo;
308       info.file_token.hi = test_handle.expected_token_hi;
309     } else {
310       info.file_token.lo = 0;
311       info.file_token.hi = 0;
312     }
313     args->nexe_desc = NaClDescIoFromFileInfo(info, NACL_ABI_O_RDONLY);
314   }
315
316   NaClThread thread;
317   CHECK(NaClThreadCtor(&thread, DummyRendererThread, &thread_args,
318                        NACL_KERN_STACK_SIZE));
319
320   NaClChromeMainStartApp(nap, args);
321   NaClLog(LOG_FATAL, "NaClChromeMainStartApp() should never return\n");
322   return 1;
323 }