| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 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 | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #include "native_client/src/trusted/service_runtime/sel_main_chrome.h" | 7 #include "native_client/src/trusted/service_runtime/sel_main_chrome.h" |
| 8 | 8 |
| 9 #include "native_client/src/include/portability.h" | 9 #include "native_client/src/include/portability.h" |
| 10 #include "native_client/src/include/portability_io.h" | 10 #include "native_client/src/include/portability_io.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 #include "native_client/src/trusted/service_runtime/nacl_globals.h" | 36 #include "native_client/src/trusted/service_runtime/nacl_globals.h" |
| 37 #include "native_client/src/trusted/service_runtime/nacl_debug_init.h" | 37 #include "native_client/src/trusted/service_runtime/nacl_debug_init.h" |
| 38 #include "native_client/src/trusted/service_runtime/nacl_signal.h" | 38 #include "native_client/src/trusted/service_runtime/nacl_signal.h" |
| 39 #include "native_client/src/trusted/service_runtime/osx/mach_exception_handler.h
" | 39 #include "native_client/src/trusted/service_runtime/osx/mach_exception_handler.h
" |
| 40 #include "native_client/src/trusted/service_runtime/sel_addrspace.h" | 40 #include "native_client/src/trusted/service_runtime/sel_addrspace.h" |
| 41 #include "native_client/src/trusted/service_runtime/sel_ldr.h" | 41 #include "native_client/src/trusted/service_runtime/sel_ldr.h" |
| 42 #include "native_client/src/trusted/service_runtime/sel_qualify.h" | 42 #include "native_client/src/trusted/service_runtime/sel_qualify.h" |
| 43 #include "native_client/src/trusted/service_runtime/win/exception_patch/ntdll_pa
tch.h" | 43 #include "native_client/src/trusted/service_runtime/win/exception_patch/ntdll_pa
tch.h" |
| 44 #include "native_client/src/trusted/validator/validation_metadata.h" | 44 #include "native_client/src/trusted/validator/validation_metadata.h" |
| 45 | 45 |
| 46 static void NaClCleanupAndExit(struct NaClApp *nap, NaClErrorCode errcode); |
| 47 |
| 46 struct NaClChromeMainArgs *NaClChromeMainArgsCreate(void) { | 48 struct NaClChromeMainArgs *NaClChromeMainArgsCreate(void) { |
| 47 struct NaClChromeMainArgs *args = malloc(sizeof(*args)); | 49 struct NaClChromeMainArgs *args = malloc(sizeof(*args)); |
| 48 if (args == NULL) | 50 if (args == NULL) |
| 49 return NULL; | 51 return NULL; |
| 50 args->imc_bootstrap_handle = NACL_INVALID_HANDLE; | 52 args->imc_bootstrap_handle = NACL_INVALID_HANDLE; |
| 51 args->irt_fd = -1; | 53 args->irt_fd = -1; |
| 52 args->initial_ipc_desc = NULL; | 54 args->initial_ipc_desc = NULL; |
| 53 args->enable_exception_handling = 0; | 55 args->enable_exception_handling = 0; |
| 54 args->enable_debug_stub = 0; | 56 args->enable_debug_stub = 0; |
| 55 args->enable_dyncode_syscalls = 1; | 57 args->enable_dyncode_syscalls = 1; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 if (errcode != LOAD_OK) { | 119 if (errcode != LOAD_OK) { |
| 118 NaClLog(LOG_FATAL, | 120 NaClLog(LOG_FATAL, |
| 119 "NaClLoadIrt: Failed to load the integrated runtime (IRT): %s\n", | 121 "NaClLoadIrt: Failed to load the integrated runtime (IRT): %s\n", |
| 120 NaClErrorString(errcode)); | 122 NaClErrorString(errcode)); |
| 121 } | 123 } |
| 122 | 124 |
| 123 NaClMetadataDtor(&metadata); | 125 NaClMetadataDtor(&metadata); |
| 124 NaClDescUnref(nd); | 126 NaClDescUnref(nd); |
| 125 } | 127 } |
| 126 | 128 |
| 127 void NaClChromeMainStart(struct NaClChromeMainArgs *args) { | 129 struct NaClApp *NaClChromeMainCreateApp(struct NaClChromeMainArgs *args) { |
| 128 char *av[1]; | 130 struct NaClApp *nap = (struct NaClApp *)malloc(sizeof(struct NaClApp)); |
| 129 int ac = 1; | |
| 130 const char **envp; | |
| 131 struct NaClApp state; | |
| 132 struct NaClApp *nap = &state; | |
| 133 NaClErrorCode errcode = LOAD_INTERNAL; | 131 NaClErrorCode errcode = LOAD_INTERNAL; |
| 134 int ret_code = 1; | |
| 135 struct NaClEnvCleanser env_cleanser; | |
| 136 int skip_qualification; | 132 int skip_qualification; |
| 137 | 133 |
| 138 #if NACL_OSX | |
| 139 /* Mac dynamic libraries cannot access the environ variable directly. */ | |
| 140 envp = (const char **) *_NSGetEnviron(); | |
| 141 #else | |
| 142 /* Overzealous code style check is overzealous. */ | |
| 143 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ | |
| 144 extern char **environ; | |
| 145 envp = (const char **) environ; | |
| 146 #endif | |
| 147 | |
| 148 #if NACL_LINUX || NACL_OSX | 134 #if NACL_LINUX || NACL_OSX |
| 149 /* This needs to happen before NaClAllModulesInit(). */ | 135 /* This needs to happen before NaClAllModulesInit(). */ |
| 150 if (args->urandom_fd != -1) | 136 if (args->urandom_fd != -1) |
| 151 NaClSecureRngModuleSetUrandomFd(args->urandom_fd); | 137 NaClSecureRngModuleSetUrandomFd(args->urandom_fd); |
| 152 #endif | 138 #endif |
| 153 | 139 |
| 154 /* | 140 /* |
| 155 * Clear state so that NaClBootstrapChannelErrorReporter will be | 141 * Clear state so that NaClBootstrapChannelErrorReporter will be |
| 156 * able to know if the bootstrap channel is available or not. | 142 * able to know if the bootstrap channel is available or not. |
| 157 */ | 143 */ |
| 158 memset(&state, 0, sizeof state); | 144 memset(nap, 0, sizeof(struct NaClApp)); |
| 159 NaClAllModulesInit(); | 145 NaClAllModulesInit(); |
| 160 NaClBootstrapChannelErrorReporterInit(); | 146 NaClBootstrapChannelErrorReporterInit(); |
| 161 NaClErrorLogHookInit(NaClBootstrapChannelErrorReporter, &state); | 147 NaClErrorLogHookInit(NaClBootstrapChannelErrorReporter, nap); |
| 162 | 148 |
| 163 /* to be passed to NaClMain, eventually... */ | 149 if (NACL_FI_ERROR_COND("AppCtor", !NaClAppCtor(nap))) { |
| 164 av[0] = "NaClMain"; | |
| 165 | |
| 166 if (NACL_FI_ERROR_COND("AppCtor", !NaClAppCtor(&state))) { | |
| 167 NaClLog(LOG_FATAL, "Error while constructing app state\n"); | 150 NaClLog(LOG_FATAL, "Error while constructing app state\n"); |
| 168 goto done; | 151 NaClCleanupAndExit(nap, errcode); |
| 152 free(nap); |
| 153 return NULL; |
| 169 } | 154 } |
| 170 | 155 |
| 171 errcode = LOAD_OK; | 156 errcode = LOAD_OK; |
| 172 | 157 |
| 173 /* Allow or disallow dyncode API based on args. */ | 158 /* Allow or disallow dyncode API based on args. */ |
| 174 nap->enable_dyncode_syscalls = args->enable_dyncode_syscalls; | 159 nap->enable_dyncode_syscalls = args->enable_dyncode_syscalls; |
| 175 nap->initial_nexe_max_code_bytes = args->initial_nexe_max_code_bytes; | 160 nap->initial_nexe_max_code_bytes = args->initial_nexe_max_code_bytes; |
| 176 | 161 |
| 177 #if NACL_LINUX | 162 #if NACL_LINUX |
| 178 g_prereserved_sandbox_size = args->prereserved_sandbox_size; | 163 g_prereserved_sandbox_size = args->prereserved_sandbox_size; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 args->attach_debug_exception_handler_func; | 247 args->attach_debug_exception_handler_func; |
| 263 #else | 248 #else |
| 264 # error Unknown host OS | 249 # error Unknown host OS |
| 265 #endif | 250 #endif |
| 266 } | 251 } |
| 267 #if NACL_LINUX | 252 #if NACL_LINUX |
| 268 NaClSignalHandlerInit(); | 253 NaClSignalHandlerInit(); |
| 269 #endif | 254 #endif |
| 270 | 255 |
| 271 /* Give debuggers a well known point at which xlate_base is known. */ | 256 /* Give debuggers a well known point at which xlate_base is known. */ |
| 272 NaClGdbHook(&state); | 257 NaClGdbHook(nap); |
| 273 | 258 |
| 274 NaClCreateServiceSocket(nap); | 259 NaClCreateServiceSocket(nap); |
| 275 /* | 260 /* |
| 276 * LOG_FATAL errors that occur before NaClSetUpBootstrapChannel will | 261 * LOG_FATAL errors that occur before NaClSetUpBootstrapChannel will |
| 277 * not be reported via the crash log mechanism (for Chromium | 262 * not be reported via the crash log mechanism (for Chromium |
| 278 * embedding of NaCl, shown in the JavaScript console). | 263 * embedding of NaCl, shown in the JavaScript console). |
| 279 * | 264 * |
| 280 * Some errors, such as due to NaClRunSelQualificationTests, do not | 265 * Some errors, such as due to NaClRunSelQualificationTests, do not |
| 281 * trigger a LOG_FATAL but instead set module_load_status to be sent | 266 * trigger a LOG_FATAL but instead set module_load_status to be sent |
| 282 * in the start_module RPC reply. Log messages associated with such | 267 * in the start_module RPC reply. Log messages associated with such |
| 283 * errors would be seen, since NaClSetUpBootstrapChannel will get | 268 * errors would be seen, since NaClSetUpBootstrapChannel will get |
| 284 * called. | 269 * called. |
| 285 */ | 270 */ |
| 286 NaClSetUpBootstrapChannel(nap, args->imc_bootstrap_handle); | 271 NaClSetUpBootstrapChannel(nap, args->imc_bootstrap_handle); |
| 287 | 272 |
| 288 NACL_FI_FATAL("BeforeSecureCommandChannel"); | 273 NACL_FI_FATAL("BeforeSecureCommandChannel"); |
| 289 /* | 274 /* |
| 290 * NB: Spawns a thread that uses the command channel. We do this | 275 * NB: Spawns a thread that uses the command channel. We do this |
| 291 * after NaClAppLoadFile so that the NaClApp object is more fully | 276 * after NaClAppLoadFile so that the NaClApp object is more fully |
| 292 * populated. Hereafter any changes to nap should be done while | 277 * populated. Hereafter any changes to nap should be done while |
| 293 * holding locks. | 278 * holding locks. |
| 294 */ | 279 */ |
| 295 NaClSecureCommandChannel(nap); | 280 NaClSecureCommandChannel(nap); |
| 296 | 281 |
| 297 NaClLog(4, "NaClSecureCommandChannel has spawned channel\n"); | 282 NaClLog(4, "NaClSecureCommandChannel has spawned channel\n"); |
| 298 | 283 |
| 299 NaClLog(4, "secure service = %"NACL_PRIxPTR"\n", | 284 NaClLog(4, "secure service = %"NACL_PRIxPTR"\n", |
| 300 (uintptr_t) nap->secure_service); | 285 (uintptr_t) nap->secure_service); |
| 286 |
| 287 if (args->enable_debug_stub) { |
| 288 #if NACL_LINUX || NACL_OSX |
| 289 if (args->debug_stub_server_bound_socket_fd != NACL_INVALID_SOCKET) { |
| 290 NaClDebugSetBoundSocket(args->debug_stub_server_bound_socket_fd); |
| 291 } |
| 292 #endif |
| 293 if (!NaClDebugInit(nap)) { |
| 294 NaClCleanupAndExit(nap, errcode); |
| 295 free(nap); |
| 296 return NULL; |
| 297 } |
| 298 } |
| 299 |
| 300 free(args); |
| 301 return nap; |
| 302 } |
| 303 |
| 304 void NaClChromeMainLoadAndRunNexe(struct NaClApp *nap, int irt_fd) { |
| 305 char *av[1]; |
| 306 int ac = 1; |
| 307 int ret_code = 1; |
| 308 NaClErrorCode errcode = LOAD_OK; |
| 309 struct NaClEnvCleanser env_cleanser; |
| 310 const char **envp; |
| 311 |
| 312 #if NACL_OSX |
| 313 /* Mac dynamic libraries cannot access the environ variable directly. */ |
| 314 envp = (const char **) *_NSGetEnviron(); |
| 315 #else |
| 316 /* Overzealous code style check is overzealous. */ |
| 317 /* @IGNORE_LINES_FOR_CODE_HYGIENE[1] */ |
| 318 extern char **environ; |
| 319 envp = (const char **) environ; |
| 320 #endif |
| 321 |
| 301 NACL_FI_FATAL("BeforeWaitForStartModule"); | 322 NACL_FI_FATAL("BeforeWaitForStartModule"); |
| 302 | 323 |
| 303 if (NULL != nap->secure_service) { | 324 if (NULL != nap->secure_service) { |
| 304 NaClErrorCode start_result; | 325 NaClErrorCode start_result; |
| 305 /* | 326 /* |
| 306 * wait for start_module RPC call on secure channel thread. | 327 * wait for start_module RPC call on secure channel thread. |
| 307 */ | 328 */ |
| 308 start_result = NaClWaitForStartModuleCommand(nap); | 329 start_result = NaClWaitForStartModuleCommand(nap); |
| 309 if (LOAD_OK == errcode) { | 330 errcode = start_result; |
| 310 errcode = start_result; | |
| 311 } | |
| 312 } | 331 } |
| 313 | 332 |
| 314 NACL_FI_FATAL("BeforeLoadIrt"); | 333 NACL_FI_FATAL("BeforeLoadIrt"); |
| 315 | 334 |
| 316 /* | 335 /* |
| 317 * error reporting done; can quit now if there was an error earlier. | 336 * error reporting done; can quit now if there was an error earlier. |
| 318 */ | 337 */ |
| 319 if (LOAD_OK != errcode) { | 338 if (LOAD_OK != errcode) { |
| 320 goto done; | 339 NaClCleanupAndExit(nap, errcode); |
| 340 return; |
| 321 } | 341 } |
| 322 | 342 |
| 323 /* | 343 /* |
| 324 * Load the integrated runtime (IRT) library. | 344 * Load the integrated runtime (IRT) library. |
| 325 */ | 345 */ |
| 326 if (args->irt_fd != -1 && !nap->irt_loaded) { | 346 if (irt_fd != -1 && !nap->irt_loaded) { |
| 327 NaClLoadIrt(nap, args->irt_fd); | 347 NaClLoadIrt(nap, irt_fd); |
| 328 nap->irt_loaded = 1; | 348 nap->irt_loaded = 1; |
| 329 } | 349 } |
| 330 | 350 |
| 331 NACL_FI_FATAL("BeforeEnvCleanserCtor"); | 351 NACL_FI_FATAL("BeforeEnvCleanserCtor"); |
| 332 | 352 |
| 333 NaClEnvCleanserCtor(&env_cleanser, 1); | 353 NaClEnvCleanserCtor(&env_cleanser, 1); |
| 334 if (!NaClEnvCleanserInit(&env_cleanser, envp, NULL)) { | 354 if (!NaClEnvCleanserInit(&env_cleanser, envp, NULL)) { |
| 335 NaClLog(LOG_FATAL, "Failed to initialise env cleanser\n"); | 355 NaClLog(LOG_FATAL, "Failed to initialise env cleanser\n"); |
| 336 } | 356 } |
| 337 | 357 |
| 338 if (NACL_FI_ERROR_COND("LaunchServiceThreads", | 358 if (NACL_FI_ERROR_COND("LaunchServiceThreads", |
| 339 !NaClAppLaunchServiceThreads(nap))) { | 359 !NaClAppLaunchServiceThreads(nap))) { |
| 340 NaClLog(LOG_FATAL, "Launch service threads failed\n"); | 360 NaClLog(LOG_FATAL, "Launch service threads failed\n"); |
| 341 } | 361 } |
| 342 | 362 |
| 343 if (args->enable_debug_stub) { | 363 /* to be passed to NaClMain, eventually... */ |
| 344 #if NACL_LINUX || NACL_OSX | 364 av[0] = "NaClMain"; |
| 345 if (args->debug_stub_server_bound_socket_fd != NACL_INVALID_SOCKET) { | |
| 346 NaClDebugSetBoundSocket(args->debug_stub_server_bound_socket_fd); | |
| 347 } | |
| 348 #endif | |
| 349 if (!NaClDebugInit(nap)) { | |
| 350 goto done; | |
| 351 } | |
| 352 } | |
| 353 | |
| 354 free(args); | |
| 355 args = NULL; | |
| 356 | 365 |
| 357 if (NACL_FI_ERROR_COND( | 366 if (NACL_FI_ERROR_COND( |
| 358 "CreateMainThread", | 367 "CreateMainThread", |
| 359 !NaClCreateMainThread(nap, ac, av, | 368 !NaClCreateMainThread(nap, ac, av, |
| 360 NaClEnvCleanserEnvironment(&env_cleanser)))) { | 369 NaClEnvCleanserEnvironment(&env_cleanser)))) { |
| 361 NaClLog(LOG_FATAL, "creating main thread failed\n"); | 370 NaClLog(LOG_FATAL, "creating main thread failed\n"); |
| 362 } | 371 } |
| 363 NACL_FI_FATAL("BeforeEnvCleanserDtor"); | 372 NACL_FI_FATAL("BeforeEnvCleanserDtor"); |
| 364 | 373 |
| 365 NaClEnvCleanserDtor(&env_cleanser); | 374 NaClEnvCleanserDtor(&env_cleanser); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 379 */ | 388 */ |
| 380 NaClLog(LOG_INFO, "NaCl untrusted code called _exit(0x%x)\n", ret_code); | 389 NaClLog(LOG_INFO, "NaCl untrusted code called _exit(0x%x)\n", ret_code); |
| 381 } | 390 } |
| 382 | 391 |
| 383 /* | 392 /* |
| 384 * exit_group or equiv kills any still running threads while module | 393 * exit_group or equiv kills any still running threads while module |
| 385 * addr space is still valid. otherwise we'd have to kill threads | 394 * addr space is still valid. otherwise we'd have to kill threads |
| 386 * before we clean up the address space. | 395 * before we clean up the address space. |
| 387 */ | 396 */ |
| 388 NaClExit(ret_code); | 397 NaClExit(ret_code); |
| 398 } |
| 389 | 399 |
| 390 done: | 400 static void NaClCleanupAndExit(struct NaClApp *nap, NaClErrorCode errcode) { |
| 391 fflush(stdout); | 401 fflush(stdout); |
| 392 | 402 |
| 393 /* | 403 /* |
| 394 * If there is a secure command channel, we sent an RPC reply with | 404 * If there is a secure command channel, we sent an RPC reply with |
| 395 * the reason that the nexe was rejected. If we exit now, that | 405 * the reason that the nexe was rejected. If we exit now, that |
| 396 * reply may still be in-flight and the various channel closure (esp | 406 * reply may still be in-flight and the various channel closure (esp |
| 397 * reverse channel) may be detected first. This would result in a | 407 * reverse channel) may be detected first. This would result in a |
| 398 * crash being reported, rather than the error in the RPC reply. | 408 * crash being reported, rather than the error in the RPC reply. |
| 399 * Instead, we wait for the hard-shutdown on the command channel. | 409 * Instead, we wait for the hard-shutdown on the command channel. |
| 400 */ | 410 */ |
| 401 if (LOAD_OK != errcode) { | 411 if (LOAD_OK != errcode) { |
| 402 NaClBlockIfCommandChannelExists(nap); | 412 NaClBlockIfCommandChannelExists(nap); |
| 403 } | 413 } |
| 404 | 414 |
| 405 NaClAllModulesFini(); | 415 NaClAllModulesFini(); |
| 406 | 416 |
| 407 NaClExit(ret_code); | 417 NaClExit(1); |
| 408 } | 418 } |
| 419 |
| 420 void NaClChromeMainStart(struct NaClChromeMainArgs *args) { |
| 421 int irt_fd = args->irt_fd; |
| 422 struct NaClApp *nap = NaClChromeMainCreateApp(args); |
| 423 if (NULL != nap) { |
| 424 NaClChromeMainLoadAndRunNexe(nap, irt_fd); |
| 425 } |
| 426 } |
| OLD | NEW |