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 <string.h>
8 :
9 : /*
10 : * NaCl Simple/secure ELF loader (NaCl SEL).
11 : */
12 : #include "native_client/src/include/portability.h"
13 : #include "native_client/src/include/portability_io.h"
14 : #include "native_client/src/include/portability_string.h"
15 : #include "native_client/src/include/nacl_macros.h"
16 :
17 : #include "native_client/src/public/desc_metadata_types.h"
18 : #include "native_client/src/public/nacl_app.h"
19 : #include "native_client/src/public/secure_service.h"
20 :
21 : #include "native_client/src/shared/gio/gio.h"
22 : #include "native_client/src/shared/platform/nacl_check.h"
23 : #include "native_client/src/shared/platform/nacl_exit.h"
24 : #include "native_client/src/shared/platform/nacl_log.h"
25 : #include "native_client/src/shared/platform/nacl_sync.h"
26 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
27 : #include "native_client/src/shared/platform/nacl_time.h"
28 : #include "native_client/src/shared/srpc/nacl_srpc.h"
29 :
30 : #include "native_client/src/trusted/desc/nacl_desc_base.h"
31 : #include "native_client/src/trusted/desc/nacl_desc_conn_cap.h"
32 : #include "native_client/src/trusted/desc/nacl_desc_imc.h"
33 : #include "native_client/src/trusted/desc/nacl_desc_io.h"
34 : #include "native_client/src/trusted/desc/nrd_xfer.h"
35 : #include "native_client/src/trusted/desc_cacheability/desc_cacheability.h"
36 : #include "native_client/src/trusted/fault_injection/fault_injection.h"
37 : #include "native_client/src/trusted/fault_injection/test_injection.h"
38 : #include "native_client/src/trusted/gio/gio_nacl_desc.h"
39 : #include "native_client/src/trusted/gio/gio_shm.h"
40 : #include "native_client/src/trusted/interval_multiset/nacl_interval_range_tree_intern.h"
41 : #include "native_client/src/trusted/service_runtime/arch/sel_ldr_arch.h"
42 : #include "native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h"
43 : #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
44 : #include "native_client/src/trusted/service_runtime/include/sys/stat.h"
45 : #include "native_client/src/trusted/service_runtime/include/sys/time.h"
46 : #include "native_client/src/trusted/service_runtime/nacl_app.h"
47 : #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
48 : #include "native_client/src/trusted/service_runtime/nacl_desc_effector_ldr.h"
49 : #include "native_client/src/trusted/service_runtime/nacl_globals.h"
50 : #include "native_client/src/trusted/service_runtime/nacl_resource.h"
51 : #include "native_client/src/trusted/service_runtime/nacl_reverse_quota_interface.h"
52 : #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h"
53 : #include "native_client/src/trusted/service_runtime/nacl_syscall_handlers.h"
54 : #include "native_client/src/trusted/service_runtime/nacl_valgrind_hooks.h"
55 : #include "native_client/src/trusted/service_runtime/name_service/default_name_service.h"
56 : #include "native_client/src/trusted/service_runtime/name_service/name_service.h"
57 : #include "native_client/src/trusted/service_runtime/sel_addrspace.h"
58 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
59 : #include "native_client/src/trusted/service_runtime/sel_memory.h"
60 : #include "native_client/src/trusted/service_runtime/sel_ldr_thread_interface.h"
61 : #include "native_client/src/trusted/simple_service/nacl_simple_rservice.h"
62 : #include "native_client/src/trusted/simple_service/nacl_simple_service.h"
63 : #include "native_client/src/trusted/threading/nacl_thread_interface.h"
64 : #include "native_client/src/trusted/validator/validation_cache.h"
65 :
66 1180 : static int IsEnvironmentVariableSet(char const *env_name) {
67 1180 : return NULL != getenv(env_name);
68 : }
69 :
70 : static int ShouldEnableDyncodeSyscalls(void) {
71 295 : return !IsEnvironmentVariableSet("NACL_DISABLE_DYNCODE_SYSCALLS");
72 : }
73 :
74 : static int ShouldEnableDynamicLoading(void) {
75 295 : return !IsEnvironmentVariableSet("NACL_DISABLE_DYNAMIC_LOADING");
76 : }
77 :
78 295 : int NaClAppWithSyscallTableCtor(struct NaClApp *nap,
79 295 : struct NaClSyscallTableEntry *table) {
80 295 : struct NaClDescEffectorLdr *effp;
81 :
82 : /* Zero-initialize in case we miss any fields below. */
83 885 : memset(nap, 0, sizeof(*nap));
84 :
85 : /* The validation cache will be injected later, if it exists. */
86 295 : nap->validation_cache = NULL;
87 :
88 295 : nap->validator = NaClCreateValidator();
89 :
90 : /* Get the set of features that the CPU we're running on supports. */
91 : /* These may be adjusted later in sel_main.c for fixed-feature CPU mode. */
92 295 : nap->cpu_features = (NaClCPUFeatures *) malloc(
93 : nap->validator->CPUFeatureSize);
94 295 : if (NULL == nap->cpu_features) {
95 0 : goto cleanup_none;
96 : }
97 295 : nap->validator->GetCurrentCPUFeatures(nap->cpu_features);
98 295 : nap->fixed_feature_cpu_mode = 0;
99 :
100 295 : nap->addr_bits = NACL_MAX_ADDR_BITS;
101 :
102 295 : nap->stack_size = NACL_DEFAULT_STACK_MAX;
103 295 : nap->initial_nexe_max_code_bytes = 0;
104 :
105 295 : nap->mem_start = 0;
106 :
107 : #if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 \
108 : && NACL_BUILD_SUBARCH == 32)
109 : nap->pcrel_thunk = 0;
110 : nap->pcrel_thunk_end = 0;
111 : #endif
112 : #if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 \
113 : && NACL_BUILD_SUBARCH == 64)
114 295 : nap->nacl_syscall_addr = 0;
115 295 : nap->get_tls_fast_path1_addr = 0;
116 295 : nap->get_tls_fast_path2_addr = 0;
117 : #endif
118 :
119 295 : nap->static_text_end = 0;
120 295 : nap->dynamic_text_start = 0;
121 295 : nap->dynamic_text_end = 0;
122 295 : nap->rodata_start = 0;
123 295 : nap->data_start = 0;
124 295 : nap->data_end = 0;
125 :
126 295 : nap->initial_entry_pt = 0;
127 295 : nap->user_entry_pt = 0;
128 :
129 295 : if (!DynArrayCtor(&nap->threads, 2)) {
130 0 : goto cleanup_cpu_features;
131 : }
132 295 : if (!DynArrayCtor(&nap->desc_tbl, 2)) {
133 0 : goto cleanup_threads;
134 : }
135 295 : if (!NaClVmmapCtor(&nap->mem_map)) {
136 0 : goto cleanup_desc_tbl;
137 : }
138 :
139 295 : nap->mem_io_regions = (struct NaClIntervalMultiset *) malloc(
140 : sizeof(struct NaClIntervalRangeTree));
141 295 : if (NULL == nap->mem_io_regions) {
142 0 : goto cleanup_mem_map;
143 : }
144 :
145 295 : if (!NaClIntervalRangeTreeCtor((struct NaClIntervalRangeTree *)
146 : nap->mem_io_regions)) {
147 0 : free(nap->mem_io_regions);
148 0 : nap->mem_io_regions = NULL;
149 0 : goto cleanup_mem_map;
150 : }
151 :
152 295 : effp = (struct NaClDescEffectorLdr *) malloc(sizeof *effp);
153 295 : if (NULL == effp) {
154 0 : goto cleanup_mem_io_regions;
155 : }
156 295 : if (!NaClDescEffectorLdrCtor(effp, nap)) {
157 0 : goto cleanup_effp_free;
158 : }
159 295 : nap->effp = (struct NaClDescEffector *) effp;
160 :
161 295 : nap->enable_dyncode_syscalls = ShouldEnableDyncodeSyscalls();
162 295 : nap->use_shm_for_dynamic_text = ShouldEnableDynamicLoading();
163 295 : nap->text_shm = NULL;
164 295 : if (!NaClMutexCtor(&nap->dynamic_load_mutex)) {
165 0 : goto cleanup_effp_free;
166 : }
167 295 : nap->dynamic_page_bitmap = NULL;
168 :
169 295 : nap->dynamic_regions = NULL;
170 295 : nap->num_dynamic_regions = 0;
171 295 : nap->dynamic_regions_allocated = 0;
172 295 : nap->dynamic_delete_generation = 0;
173 :
174 295 : nap->dynamic_mapcache_offset = 0;
175 295 : nap->dynamic_mapcache_size = 0;
176 295 : nap->dynamic_mapcache_ret = 0;
177 :
178 295 : nap->service_port = NULL;
179 295 : nap->service_address = NULL;
180 295 : nap->secure_service_port = NULL;
181 295 : nap->secure_service_address = NULL;
182 295 : nap->bootstrap_channel = NULL;
183 295 : nap->secure_service = NULL;
184 295 : nap->irt_loaded = 0;
185 295 : nap->main_exe_prevalidated = 0;
186 :
187 295 : nap->kernel_service = NULL;
188 295 : nap->resource_phase = NACL_RESOURCE_PHASE_START;
189 295 : if (!NaClResourceNaClAppInit(&nap->resources, nap)) {
190 0 : goto cleanup_dynamic_load_mutex;
191 : }
192 :
193 295 : if (!NaClMutexCtor(&nap->mu)) {
194 0 : goto cleanup_dynamic_load_mutex;
195 : }
196 295 : if (!NaClCondVarCtor(&nap->cv)) {
197 0 : goto cleanup_mu;
198 : }
199 :
200 : #if NACL_WINDOWS
201 : nap->vm_hole_may_exist = 0;
202 : nap->threads_launching = 0;
203 : #endif
204 :
205 295 : nap->syscall_table = table;
206 :
207 295 : nap->runtime_host_interface = NULL;
208 295 : nap->desc_quota_interface = NULL;
209 :
210 295 : nap->module_initialization_state = NACL_MODULE_UNINITIALIZED;
211 295 : nap->module_load_status = LOAD_STATUS_UNKNOWN;
212 :
213 295 : nap->name_service = (struct NaClNameService *) malloc(
214 : sizeof *nap->name_service);
215 295 : if (NULL == nap->name_service) {
216 0 : goto cleanup_cv;
217 : }
218 295 : if (!NaClNameServiceCtor(nap->name_service,
219 : NaClAddrSpSquattingThreadIfFactoryFunction,
220 : (void *) nap)) {
221 0 : free(nap->name_service);
222 0 : goto cleanup_cv;
223 : }
224 295 : nap->name_service_conn_cap = NaClDescRef(nap->name_service->
225 : base.base.bound_and_cap[1]);
226 295 : if (!NaClDefaultNameServiceInit(nap->name_service)) {
227 0 : goto cleanup_name_service;
228 : }
229 :
230 295 : nap->ignore_validator_result = 0;
231 295 : nap->skip_validator = 0;
232 295 : nap->validator_stub_out_mode = 0;
233 :
234 295 : if (IsEnvironmentVariableSet("NACL_DANGEROUS_ENABLE_FILE_ACCESS")) {
235 0 : NaClInsecurelyBypassAllAclChecks();
236 0 : NaClLog(LOG_INFO, "DANGER: ENABLED FILE ACCESS\n");
237 0 : }
238 :
239 295 : nap->enable_list_mappings = 0;
240 295 : if (IsEnvironmentVariableSet("NACL_DANGEROUS_ENABLE_LIST_MAPPINGS")) {
241 : /*
242 : * This syscall is not actually know to be dangerous, but is not yet
243 : * exposed by our public API.
244 : */
245 1 : NaClLog(LOG_INFO, "DANGER: ENABLED LIST_MAPPINGS\n");
246 1 : nap->enable_list_mappings = 1;
247 1 : }
248 295 : nap->pnacl_mode = 0;
249 :
250 295 : if (!NaClMutexCtor(&nap->threads_mu)) {
251 0 : goto cleanup_name_service;
252 : }
253 295 : nap->num_threads = 0;
254 295 : if (!NaClFastMutexCtor(&nap->desc_mu)) {
255 0 : goto cleanup_threads_mu;
256 : }
257 :
258 295 : nap->running = 0;
259 295 : nap->exit_status = -1;
260 :
261 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
262 : nap->code_seg_sel = 0;
263 : nap->data_seg_sel = 0;
264 : #endif
265 :
266 295 : nap->debug_stub_callbacks = NULL;
267 : #if NACL_WINDOWS
268 : nap->debug_stub_port = 0;
269 : #endif
270 295 : nap->main_nexe_desc = NULL;
271 295 : nap->irt_nexe_desc = NULL;
272 :
273 295 : nap->exception_handler = 0;
274 295 : if (!NaClMutexCtor(&nap->exception_mu)) {
275 0 : goto cleanup_desc_mu;
276 : }
277 295 : nap->enable_exception_handling = 0;
278 : #if NACL_WINDOWS
279 : nap->debug_exception_handler_state = NACL_DEBUG_EXCEPTION_HANDLER_NOT_STARTED;
280 : nap->attach_debug_exception_handler_func = NULL;
281 : #endif
282 295 : nap->enable_faulted_thread_queue = 0;
283 295 : nap->faulted_thread_count = 0;
284 : #if NACL_WINDOWS
285 : nap->faulted_thread_event = INVALID_HANDLE_VALUE;
286 : #else
287 295 : nap->faulted_thread_fd_read = -1;
288 295 : nap->faulted_thread_fd_write = -1;
289 : #endif
290 :
291 :
292 : #if NACL_LINUX || NACL_OSX
293 : /*
294 : * Try to pre-cache information that we can't obtain with the outer
295 : * sandbox on. If the outer sandbox has already been enabled, this
296 : * will just set sc_nprocessors_onln to -1, and it is the
297 : * responsibility of the caller to replace this with a sane value
298 : * after the Ctor returns.
299 : */
300 295 : nap->sc_nprocessors_onln = sysconf(_SC_NPROCESSORS_ONLN);
301 : #endif
302 :
303 295 : if (!NaClMutexCtor(&nap->futex_wait_list_mu)) {
304 0 : goto cleanup_exception_mu;
305 : }
306 295 : nap->futex_wait_list_head.next = &nap->futex_wait_list_head;
307 295 : nap->futex_wait_list_head.prev = &nap->futex_wait_list_head;
308 :
309 295 : return 1;
310 :
311 : cleanup_exception_mu:
312 0 : NaClMutexDtor(&nap->exception_mu);
313 : cleanup_desc_mu:
314 0 : NaClFastMutexDtor(&nap->desc_mu);
315 : cleanup_threads_mu:
316 0 : NaClMutexDtor(&nap->threads_mu);
317 : cleanup_name_service:
318 0 : NaClDescUnref(nap->name_service_conn_cap);
319 0 : NaClRefCountUnref((struct NaClRefCount *) nap->name_service);
320 : cleanup_cv:
321 0 : NaClCondVarDtor(&nap->cv);
322 : cleanup_mu:
323 0 : NaClMutexDtor(&nap->mu);
324 : cleanup_dynamic_load_mutex:
325 0 : NaClMutexDtor(&nap->dynamic_load_mutex);
326 : cleanup_effp_free:
327 0 : free(nap->effp);
328 : cleanup_mem_io_regions:
329 0 : NaClIntervalMultisetDelete(nap->mem_io_regions);
330 0 : nap->mem_io_regions = NULL;
331 : cleanup_mem_map:
332 0 : NaClVmmapDtor(&nap->mem_map);
333 : cleanup_desc_tbl:
334 0 : DynArrayDtor(&nap->desc_tbl);
335 : cleanup_threads:
336 0 : DynArrayDtor(&nap->threads);
337 : cleanup_cpu_features:
338 0 : free(nap->cpu_features);
339 : cleanup_none:
340 0 : return 0;
341 295 : }
342 :
343 295 : int NaClAppCtor(struct NaClApp *nap) {
344 295 : return NaClAppWithSyscallTableCtor(nap, nacl_syscall);
345 : }
346 :
347 : struct NaClApp *NaClAppCreate(void) {
348 8 : struct NaClApp *nap = malloc(sizeof(struct NaClApp));
349 4 : if (nap == NULL)
350 0 : NaClLog(LOG_FATAL, "Failed to allocate NaClApp\n");
351 4 : if (!NaClAppCtor(nap))
352 0 : NaClLog(LOG_FATAL, "NaClAppCtor() failed\n");
353 4 : return nap;
354 : }
355 :
356 : /*
357 : * unaligned little-endian load. precondition: nbytes should never be
358 : * more than 8.
359 : */
360 0 : static uint64_t NaClLoadMem(uintptr_t addr,
361 0 : size_t user_nbytes) {
362 0 : uint64_t value = 0;
363 :
364 0 : CHECK(0 != user_nbytes && user_nbytes <= 8);
365 :
366 0 : do {
367 0 : value = value << 8;
368 0 : value |= ((uint8_t *) addr)[--user_nbytes];
369 0 : } while (user_nbytes > 0);
370 0 : return value;
371 : }
372 :
373 : #define GENERIC_LOAD(bits) \
374 : static uint ## bits ## _t NaClLoad ## bits(uintptr_t addr) { \
375 : return (uint ## bits ## _t) NaClLoadMem(addr, sizeof(uint ## bits ## _t)); \
376 : }
377 :
378 : #if NACL_TARGET_SUBARCH == 32
379 : GENERIC_LOAD(32)
380 : #endif
381 0 : GENERIC_LOAD(64)
382 :
383 : #undef GENERIC_LOAD
384 :
385 : /*
386 : * unaligned little-endian store
387 : */
388 1085970 : static void NaClStoreMem(uintptr_t addr,
389 1085970 : size_t nbytes,
390 1085970 : uint64_t value) {
391 1085970 : size_t i;
392 :
393 3257910 : CHECK(nbytes <= 8);
394 :
395 15203580 : for (i = 0; i < nbytes; ++i) {
396 6515820 : ((uint8_t *) addr)[i] = (uint8_t) value;
397 6515820 : value = value >> 8;
398 6515820 : }
399 1085970 : }
400 :
401 : #define GENERIC_STORE(bits) \
402 : static void NaClStore ## bits(uintptr_t addr, \
403 : uint ## bits ## _t v) { \
404 : NaClStoreMem(addr, sizeof(uint ## bits ## _t), v); \
405 : }
406 :
407 0 : GENERIC_STORE(16)
408 542985 : GENERIC_STORE(32)
409 542985 : GENERIC_STORE(64)
410 :
411 : #undef GENERIC_STORE
412 :
413 542985 : struct NaClPatchInfo *NaClPatchInfoCtor(struct NaClPatchInfo *self) {
414 542985 : if (NULL != self) {
415 1628955 : memset(self, 0, sizeof *self);
416 542985 : }
417 542985 : return self;
418 : }
419 :
420 : /*
421 : * This function is called by NaClLoadTrampoline and NaClLoadSpringboard to
422 : * patch a single memory location specified in NaClPatchInfo structure.
423 : */
424 542985 : void NaClApplyPatchToMemory(struct NaClPatchInfo *patch) {
425 542985 : size_t i;
426 542985 : size_t offset;
427 542985 : int64_t reloc;
428 542985 : uintptr_t target_addr;
429 :
430 1628955 : memcpy((void *) patch->dst, (void *) patch->src, patch->nbytes);
431 :
432 542985 : reloc = patch->dst - patch->src;
433 :
434 :
435 2171940 : for (i = 0; i < patch->num_abs64; ++i) {
436 542985 : offset = patch->abs64[i].target - patch->src;
437 542985 : target_addr = patch->dst + offset;
438 542985 : NaClStore64(target_addr, patch->abs64[i].value);
439 542985 : }
440 :
441 2171940 : for (i = 0; i < patch->num_abs32; ++i) {
442 542985 : offset = patch->abs32[i].target - patch->src;
443 542985 : target_addr = patch->dst + offset;
444 542985 : NaClStore32(target_addr, (uint32_t) patch->abs32[i].value);
445 542985 : }
446 :
447 1085970 : for (i = 0; i < patch->num_abs16; ++i) {
448 0 : offset = patch->abs16[i].target - patch->src;
449 0 : target_addr = patch->dst + offset;
450 0 : NaClStore16(target_addr, (uint16_t) patch->abs16[i].value);
451 0 : }
452 :
453 1085970 : for (i = 0; i < patch->num_rel64; ++i) {
454 0 : offset = patch->rel64[i] - patch->src;
455 0 : target_addr = patch->dst + offset;
456 0 : NaClStore64(target_addr, NaClLoad64(target_addr) - reloc);
457 0 : }
458 :
459 : /*
460 : * rel32 is only supported on 32-bit architectures. The range of a relative
461 : * relocation in untrusted space is +/- 4GB. This can be represented as
462 : * an unsigned 32-bit value mod 2^32, which is handy on a 32 bit system since
463 : * all 32-bit pointer arithmetic is implicitly mod 2^32. On a 64 bit system,
464 : * however, pointer arithmetic is implicitly modulo 2^64, which isn't as
465 : * helpful for our purposes. We could simulate the 32-bit behavior by
466 : * explicitly modding all relative addresses by 2^32, but that seems like an
467 : * expensive way to save a few bytes per reloc.
468 : */
469 : #if NACL_TARGET_SUBARCH == 32
470 : for (i = 0; i < patch->num_rel32; ++i) {
471 : offset = patch->rel32[i] - patch->src;
472 : target_addr = patch->dst + offset;
473 : NaClStore32(target_addr,
474 : (uint32_t) NaClLoad32(target_addr) - (int32_t) reloc);
475 : }
476 : #endif
477 542985 : }
478 :
479 :
480 : /*
481 : * Install syscall trampolines at all possible well-formed entry
482 : * points within the trampoline pages. Many of these syscalls will
483 : * correspond to unimplemented system calls and will just abort the
484 : * program.
485 : */
486 265 : void NaClLoadTrampoline(struct NaClApp *nap, enum NaClAslrMode aslr_mode) {
487 265 : int num_syscalls;
488 265 : int i;
489 265 : uintptr_t addr;
490 :
491 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
492 : if (!NaClMakePcrelThunk(nap, aslr_mode)) {
493 : NaClLog(LOG_FATAL, "NaClMakePcrelThunk failed!\n");
494 : }
495 : #else
496 530 : UNREFERENCED_PARAMETER(aslr_mode);
497 : #endif
498 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
499 265 : if (!NaClMakeDispatchAddrs(nap)) {
500 0 : NaClLog(LOG_FATAL, "NaClMakeDispatchAddrs failed!\n");
501 0 : }
502 : #endif
503 265 : NaClFillTrampolineRegion(nap);
504 :
505 : /*
506 : * Do not bother to fill in the contents of page 0, since we make it
507 : * inaccessible later (see sel_addrspace.c, NaClMemoryProtection)
508 : * anyway to help detect NULL pointer errors, and we might as well
509 : * not dirty the page.
510 : *
511 : * The last syscall entry point is used for springboard code.
512 : */
513 265 : num_syscalls = ((NACL_TRAMPOLINE_END - NACL_SYSCALL_START_ADDR)
514 : / NACL_SYSCALL_BLOCK_SIZE) - 1;
515 :
516 265 : NaClLog(2, "num_syscalls = %d (0x%x)\n", num_syscalls, num_syscalls);
517 :
518 542985 : for (i = 0, addr = nap->mem_start + NACL_SYSCALL_START_ADDR;
519 : i < num_syscalls;
520 542455 : ++i, addr += NACL_SYSCALL_BLOCK_SIZE) {
521 542455 : NaClPatchOneTrampoline(nap, addr);
522 542455 : }
523 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
524 265 : NaClPatchOneTrampolineCall(nap->get_tls_fast_path1_addr,
525 : nap->mem_start + NACL_SYSCALL_START_ADDR
526 : + NACL_SYSCALL_BLOCK_SIZE * NACL_sys_tls_get);
527 265 : NaClPatchOneTrampolineCall(nap->get_tls_fast_path2_addr,
528 : nap->mem_start + NACL_SYSCALL_START_ADDR
529 : + (NACL_SYSCALL_BLOCK_SIZE *
530 : NACL_sys_second_tls_get));
531 : #endif
532 :
533 796 : NACL_TEST_INJECTION(ChangeTrampolines, (nap));
534 265 : }
535 :
536 119 : void NaClMemRegionPrinter(void *state,
537 119 : struct NaClVmmapEntry *entry) {
538 119 : struct Gio *gp = (struct Gio *) state;
539 :
540 119 : gprintf(gp, "\nPage %"NACL_PRIdPTR" (0x%"NACL_PRIxPTR")\n",
541 : entry->page_num, entry->page_num);
542 119 : gprintf(gp, "npages %"NACL_PRIdS" (0x%"NACL_PRIxS")\n", entry->npages,
543 : entry->npages);
544 119 : gprintf(gp, "start vaddr 0x%"NACL_PRIxPTR"\n",
545 : entry->page_num << NACL_PAGESHIFT);
546 119 : gprintf(gp, "end vaddr 0x%"NACL_PRIxPTR"\n",
547 : (entry->page_num + entry->npages) << NACL_PAGESHIFT);
548 119 : gprintf(gp, "prot 0x%08x\n", entry->prot);
549 119 : gprintf(gp, "%sshared/backed by a file\n",
550 : (NULL == entry->desc) ? "not " : "");
551 119 : }
552 :
553 20 : void NaClAppPrintDetails(struct NaClApp *nap,
554 20 : struct Gio *gp) {
555 20 : NaClXMutexLock(&nap->mu);
556 20 : gprintf(gp,
557 : "NaClAppPrintDetails((struct NaClApp *) 0x%08"NACL_PRIxPTR","
558 : "(struct Gio *) 0x%08"NACL_PRIxPTR")\n", (uintptr_t) nap,
559 : (uintptr_t) gp);
560 20 : gprintf(gp, "addr space size: 2**%"NACL_PRId32"\n", nap->addr_bits);
561 20 : gprintf(gp, "stack size: 0x%08"NACL_PRIx32"\n", nap->stack_size);
562 :
563 20 : gprintf(gp, "mem start addr: 0x%08"NACL_PRIxPTR"\n", nap->mem_start);
564 : /* 123456789012345678901234567890 */
565 :
566 20 : gprintf(gp, "static_text_end: 0x%08"NACL_PRIxPTR"\n", nap->static_text_end);
567 40 : gprintf(gp, "end-of-text: 0x%08"NACL_PRIxPTR"\n",
568 20 : NaClEndOfStaticText(nap));
569 20 : gprintf(gp, "rodata: 0x%08"NACL_PRIxPTR"\n", nap->rodata_start);
570 20 : gprintf(gp, "data: 0x%08"NACL_PRIxPTR"\n", nap->data_start);
571 20 : gprintf(gp, "data_end: 0x%08"NACL_PRIxPTR"\n", nap->data_end);
572 20 : gprintf(gp, "break_addr: 0x%08"NACL_PRIxPTR"\n", nap->break_addr);
573 :
574 20 : gprintf(gp, "ELF initial entry point: 0x%08x\n", nap->initial_entry_pt);
575 20 : gprintf(gp, "ELF user entry point: 0x%08x\n", nap->user_entry_pt);
576 20 : gprintf(gp, "memory map:\n");
577 20 : NaClVmmapVisit(&nap->mem_map,
578 : NaClMemRegionPrinter,
579 : gp);
580 20 : NaClXMutexUnlock(&nap->mu);
581 20 : }
582 :
583 71579 : struct NaClDesc *NaClAppGetDescMu(struct NaClApp *nap,
584 71579 : int d) {
585 71579 : struct NaClDesc *result;
586 :
587 71579 : result = (struct NaClDesc *) DynArrayGet(&nap->desc_tbl, d);
588 71579 : if (NULL != result) {
589 71555 : NaClDescRef(result);
590 71555 : }
591 :
592 71579 : return result;
593 : }
594 :
595 1794 : void NaClAppSetDescMu(struct NaClApp *nap,
596 1794 : int d,
597 1794 : struct NaClDesc *ndp) {
598 1794 : struct NaClDesc *result;
599 :
600 1794 : result = (struct NaClDesc *) DynArrayGet(&nap->desc_tbl, d);
601 1794 : NaClDescSafeUnref(result);
602 :
603 1794 : if (!DynArraySet(&nap->desc_tbl, d, ndp)) {
604 0 : NaClLog(LOG_FATAL,
605 : "NaClAppSetDesc: could not set descriptor %d to 0x%08"
606 : NACL_PRIxPTR"\n",
607 : d,
608 : (uintptr_t) ndp);
609 0 : }
610 1794 : }
611 :
612 278 : int32_t NaClAppSetDescAvailMu(struct NaClApp *nap,
613 278 : struct NaClDesc *ndp) {
614 278 : size_t pos;
615 :
616 278 : pos = DynArrayFirstAvail(&nap->desc_tbl);
617 :
618 278 : if (pos > INT32_MAX) {
619 0 : NaClLog(LOG_FATAL,
620 : ("NaClAppSetDescAvailMu: DynArrayFirstAvail returned a value"
621 : " that is greather than 2**31-1.\n"));
622 0 : }
623 :
624 278 : NaClAppSetDescMu(nap, (int) pos, ndp);
625 :
626 278 : return (int32_t) pos;
627 : }
628 :
629 70900 : struct NaClDesc *NaClAppGetDesc(struct NaClApp *nap,
630 70900 : int d) {
631 70900 : struct NaClDesc *res;
632 :
633 70900 : NaClFastMutexLock(&nap->desc_mu);
634 70900 : res = NaClAppGetDescMu(nap, d);
635 70900 : NaClFastMutexUnlock(&nap->desc_mu);
636 70900 : return res;
637 : }
638 :
639 844 : void NaClAppSetDesc(struct NaClApp *nap,
640 844 : int d,
641 844 : struct NaClDesc *ndp) {
642 844 : NaClFastMutexLock(&nap->desc_mu);
643 844 : NaClAppSetDescMu(nap, d, ndp);
644 844 : NaClFastMutexUnlock(&nap->desc_mu);
645 844 : }
646 :
647 278 : int32_t NaClAppSetDescAvail(struct NaClApp *nap,
648 278 : struct NaClDesc *ndp) {
649 278 : int32_t pos;
650 :
651 278 : NaClFastMutexLock(&nap->desc_mu);
652 278 : pos = NaClAppSetDescAvailMu(nap, ndp);
653 278 : NaClFastMutexUnlock(&nap->desc_mu);
654 :
655 278 : return pos;
656 : }
657 :
658 20888 : int NaClAddThreadMu(struct NaClApp *nap,
659 20888 : struct NaClAppThread *natp) {
660 20888 : size_t pos;
661 :
662 20888 : pos = DynArrayFirstAvail(&nap->threads);
663 :
664 20888 : if (!DynArraySet(&nap->threads, pos, natp)) {
665 0 : NaClLog(LOG_FATAL,
666 : "NaClAddThreadMu: DynArraySet at position %"NACL_PRIuS" failed\n",
667 : pos);
668 0 : }
669 20888 : ++nap->num_threads;
670 20888 : return (int) pos;
671 : }
672 :
673 7 : int NaClAddThread(struct NaClApp *nap,
674 7 : struct NaClAppThread *natp) {
675 7 : int pos;
676 :
677 7 : NaClXMutexLock(&nap->threads_mu);
678 7 : pos = NaClAddThreadMu(nap, natp);
679 7 : NaClXMutexUnlock(&nap->threads_mu);
680 :
681 7 : return pos;
682 : }
683 :
684 19618 : void NaClRemoveThreadMu(struct NaClApp *nap,
685 19618 : int thread_num) {
686 19618 : if (NULL == DynArrayGet(&nap->threads, thread_num)) {
687 1 : NaClLog(LOG_FATAL,
688 : "NaClRemoveThreadMu:: thread to be removed is not in the table\n");
689 1 : }
690 19617 : if (nap->num_threads == 0) {
691 0 : NaClLog(LOG_FATAL,
692 : "NaClRemoveThreadMu:: num_threads cannot be 0!!!\n");
693 0 : }
694 19617 : --nap->num_threads;
695 19617 : if (!DynArraySet(&nap->threads, thread_num, (struct NaClAppThread *) NULL)) {
696 0 : NaClLog(LOG_FATAL,
697 : "NaClRemoveThreadMu:: DynArraySet at position %d failed\n",
698 : thread_num);
699 0 : }
700 19617 : }
701 :
702 3 : void NaClRemoveThread(struct NaClApp *nap,
703 3 : int thread_num) {
704 3 : NaClXMutexLock(&nap->threads_mu);
705 3 : NaClRemoveThreadMu(nap, thread_num);
706 3 : NaClXMutexUnlock(&nap->threads_mu);
707 3 : }
708 :
709 35802 : struct NaClAppThread *NaClGetThreadMu(struct NaClApp *nap,
710 35802 : int thread_num) {
711 35802 : return (struct NaClAppThread *) DynArrayGet(&nap->threads, thread_num);
712 : }
713 :
714 808 : void NaClAddHostDescriptor(struct NaClApp *nap,
715 808 : int host_os_desc,
716 808 : int flag,
717 808 : int nacl_desc) {
718 808 : struct NaClDescIoDesc *dp;
719 :
720 808 : NaClLog(4,
721 : "NaClAddHostDescriptor: host %d as nacl desc %d, flag 0x%x\n",
722 : host_os_desc,
723 : nacl_desc,
724 : flag);
725 808 : dp = NaClDescIoDescMake(NaClHostDescPosixMake(host_os_desc, flag));
726 808 : if (NULL == dp) {
727 0 : NaClLog(LOG_FATAL, "NaClAddHostDescriptor: NaClDescIoDescMake failed\n");
728 0 : }
729 808 : NaClAppSetDesc(nap, nacl_desc, (struct NaClDesc *) dp);
730 808 : }
731 :
732 2 : void NaClAddImcHandle(struct NaClApp *nap,
733 2 : NaClHandle h,
734 2 : int nacl_desc) {
735 2 : struct NaClDescImcDesc *dp;
736 :
737 2 : NaClLog(4,
738 : ("NaClAddImcHandle: importing NaClHandle %"NACL_PRIxPTR
739 : " as nacl desc %d\n"),
740 : (uintptr_t) h,
741 : nacl_desc);
742 2 : dp = (struct NaClDescImcDesc *) malloc(sizeof *dp);
743 4 : if (NACL_FI_ERROR_COND("NaClAddImcHandle__malloc", NULL == dp)) {
744 0 : NaClLog(LOG_FATAL, "NaClAddImcHandle: no memory\n");
745 0 : }
746 4 : if (NACL_FI_ERROR_COND("NaClAddImcHandle__ctor",
747 : !NaClDescImcDescCtor(dp, h))) {
748 0 : NaClLog(LOG_FATAL, ("NaClAddImcHandle: cannot construct"
749 : " IMC descriptor object\n"));
750 0 : }
751 2 : NaClAppSetDesc(nap, nacl_desc, (struct NaClDesc *) dp);
752 2 : }
753 :
754 :
755 : static struct {
756 : int d;
757 : char const *env_name;
758 : int nacl_flags;
759 : int mode;
760 : } const g_nacl_redir_control[] = {
761 : { 0, "NACL_EXE_STDIN",
762 : NACL_ABI_O_RDONLY, 0, },
763 : { 1, "NACL_EXE_STDOUT",
764 : NACL_ABI_O_WRONLY | NACL_ABI_O_APPEND | NACL_ABI_O_CREAT, 0777, },
765 : { 2, "NACL_EXE_STDERR",
766 : NACL_ABI_O_WRONLY | NACL_ABI_O_APPEND | NACL_ABI_O_CREAT, 0777, },
767 : };
768 :
769 : /*
770 : * File redirection is impossible if an outer sandbox is in place.
771 : * For the command-line embedding, we sometimes have an outer sandbox:
772 : * on OSX, it is enabled after loading the file is loaded. On the
773 : * other hand, device redirection (DEBUG_ONLY:dev://postmessage) is
774 : * impossible until the reverse channel setup has occurred.
775 : *
776 : * Because of this, we run NaClProcessRedirControl twice: once to
777 : * process default inheritance, file redirection early on, and once
778 : * after the reverse channel is in place to handle the device
779 : * redirection. We try to hide knowledge about which redirection
780 : * control values can be handled in which phases by allowing the
781 : * NaClResourceOpen to fail, and only in the last phase do we check
782 : * that the redirection succeeded in *some* phase.
783 : */
784 273 : static void NaClProcessRedirControl(struct NaClApp *nap) {
785 :
786 273 : size_t ix;
787 273 : char const *env;
788 273 : struct NaClDesc *ndp;
789 :
790 2184 : for (ix = 0; ix < NACL_ARRAY_SIZE(g_nacl_redir_control); ++ix) {
791 819 : ndp = NULL;
792 819 : if (NULL != (env = getenv(g_nacl_redir_control[ix].env_name))) {
793 2 : NaClLog(4, "getenv(%s) -> %s\n", g_nacl_redir_control[ix].env_name, env);
794 2 : ndp = NaClResourceOpen((struct NaClResource *) &nap->resources,
795 : env,
796 : g_nacl_redir_control[ix].nacl_flags,
797 : g_nacl_redir_control[ix].mode);
798 2 : NaClLog(4, " NaClResourceOpen returned %"NACL_PRIxPTR"\n",
799 : (uintptr_t) ndp);
800 2 : }
801 :
802 819 : if (NULL != ndp) {
803 2 : NaClLog(4, "Setting descriptor %d\n", (int) ix);
804 2 : NaClAppSetDesc(nap, (int) ix, ndp);
805 819 : } else if (NACL_RESOURCE_PHASE_START == nap->resource_phase) {
806 : /*
807 : * Environment not set or redirect failed -- handle default inheritance.
808 : */
809 808 : NaClAddHostDescriptor(nap, DUP(g_nacl_redir_control[ix].d),
810 : g_nacl_redir_control[ix].nacl_flags, (int) ix);
811 808 : }
812 819 : }
813 273 : }
814 :
815 : /*
816 : * Process default descriptor inheritance. This means dup'ing
817 : * descriptors 0-2 and making them available to the NaCl App.
818 : *
819 : * When standard input is inherited, this could result in a NaCl
820 : * module competing for input from the terminal; for graphical /
821 : * browser plugin environments, this never is allowed to happen, and
822 : * having this is useful for debugging, and for potential standalone
823 : * text-mode applications of NaCl.
824 : *
825 : * TODO(bsy): consider whether default inheritance should occur only
826 : * in debug mode.
827 : */
828 270 : void NaClAppInitialDescriptorHookup(struct NaClApp *nap) {
829 :
830 270 : NaClLog(4, "Processing I/O redirection/inheritance from environment\n");
831 270 : nap->resource_phase = NACL_RESOURCE_PHASE_START;
832 270 : NaClProcessRedirControl(nap);
833 270 : NaClLog(4, "... done.\n");
834 270 : }
835 :
836 11 : void NaClCreateServiceSocket(struct NaClApp *nap) {
837 11 : struct NaClDesc *secure_pair[2];
838 11 : struct NaClDesc *pair[2];
839 :
840 11 : NaClLog(3, "Entered NaClCreateServiceSocket\n");
841 :
842 22 : if (NACL_FI_ERROR_COND("NaClCreateServiceSocket__secure_boundsock",
843 : 0 != NaClCommonDescMakeBoundSock(secure_pair))) {
844 0 : NaClLog(LOG_FATAL, "Cound not create secure service socket\n");
845 0 : }
846 11 : NaClLog(4,
847 : "got bound socket at 0x%08"NACL_PRIxPTR", "
848 : "addr at 0x%08"NACL_PRIxPTR"\n",
849 : (uintptr_t) secure_pair[0],
850 : (uintptr_t) secure_pair[1]);
851 :
852 11 : NaClDescSafeUnref(nap->secure_service_port);
853 11 : nap->secure_service_port = secure_pair[0];
854 :
855 11 : NaClDescSafeUnref(nap->secure_service_address);
856 11 : nap->secure_service_address = secure_pair[1];
857 :
858 22 : if (NACL_FI_ERROR_COND("NaClCreateServiceSocket__boundsock",
859 : 0 != NaClCommonDescMakeBoundSock(pair))) {
860 0 : NaClLog(LOG_FATAL, "Cound not create service socket\n");
861 0 : }
862 11 : NaClLog(4,
863 : "got bound socket at 0x%08"NACL_PRIxPTR", "
864 : "addr at 0x%08"NACL_PRIxPTR"\n",
865 : (uintptr_t) pair[0],
866 : (uintptr_t) pair[1]);
867 11 : NaClAppSetDesc(nap, NACL_SERVICE_PORT_DESCRIPTOR, pair[0]);
868 11 : NaClAppSetDesc(nap, NACL_SERVICE_ADDRESS_DESCRIPTOR, pair[1]);
869 :
870 11 : NaClDescSafeUnref(nap->service_port);
871 :
872 11 : nap->service_port = pair[0];
873 11 : NaClDescRef(nap->service_port);
874 :
875 11 : NaClDescSafeUnref(nap->service_address);
876 :
877 11 : nap->service_address = pair[1];
878 11 : NaClDescRef(nap->service_address);
879 :
880 11 : NaClLog(4, "Leaving NaClCreateServiceSocket\n");
881 11 : }
882 :
883 : /*
884 : * Import the |inherited_desc| descriptor as an IMC handle, save a
885 : * reference to it at nap->bootstrap_channel, then send the
886 : * service_address over that channel.
887 : */
888 10 : void NaClSetUpBootstrapChannel(struct NaClApp *nap,
889 10 : NaClHandle inherited_desc) {
890 10 : struct NaClDescImcDesc *channel;
891 10 : struct NaClImcTypedMsgHdr hdr;
892 10 : struct NaClDesc *descs[2];
893 10 : ssize_t rv;
894 :
895 10 : NaClLog(4,
896 : "NaClSetUpBootstrapChannel(0x%08"NACL_PRIxPTR", %"NACL_PRIdPTR")\n",
897 : (uintptr_t) nap,
898 : (uintptr_t) inherited_desc);
899 :
900 10 : channel = (struct NaClDescImcDesc *) malloc(sizeof *channel);
901 10 : if (NULL == channel) {
902 0 : NaClLog(LOG_FATAL, "NaClSetUpBootstrapChannel: no memory\n");
903 0 : }
904 10 : if (!NaClDescImcDescCtor(channel, inherited_desc)) {
905 0 : NaClLog(LOG_FATAL,
906 : ("NaClSetUpBootstrapChannel: cannot construct IMC descriptor"
907 : " object for inherited descriptor %"NACL_PRIdPTR"\n"),
908 : (uintptr_t) inherited_desc);
909 0 : return;
910 : }
911 10 : if (NULL == nap->secure_service_address) {
912 0 : NaClLog(LOG_FATAL,
913 : "NaClSetUpBootstrapChannel: secure service address not set\n");
914 0 : return;
915 : }
916 10 : if (NULL == nap->service_address) {
917 0 : NaClLog(LOG_FATAL,
918 : "NaClSetUpBootstrapChannel: service address not set\n");
919 0 : return;
920 : }
921 : /*
922 : * service_address and service_port are set together.
923 : */
924 10 : descs[0] = nap->secure_service_address;
925 10 : descs[1] = nap->service_address;
926 :
927 10 : hdr.iov = (struct NaClImcMsgIoVec *) NULL;
928 10 : hdr.iov_length = 0;
929 10 : hdr.ndescv = descs;
930 10 : hdr.ndesc_length = NACL_ARRAY_SIZE(descs);
931 :
932 10 : rv = (*NACL_VTBL(NaClDesc, channel)->SendMsg)((struct NaClDesc *) channel,
933 : &hdr, 0);
934 10 : NaClXMutexLock(&nap->mu);
935 10 : if (NULL != nap->bootstrap_channel) {
936 0 : NaClLog(LOG_FATAL,
937 : "NaClSetUpBootstrapChannel: cannot have two bootstrap channels\n");
938 0 : }
939 10 : nap->bootstrap_channel = (struct NaClDesc *) channel;
940 10 : channel = NULL;
941 10 : NaClXMutexUnlock(&nap->mu);
942 :
943 10 : NaClLog(1,
944 : ("NaClSetUpBootstrapChannel: descriptor %"NACL_PRIdPTR
945 : ", error %"NACL_PRIdS"\n"),
946 : (uintptr_t) inherited_desc,
947 : rv);
948 20 : if (NACL_FI_ERROR_COND("NaClSetUpBootstrapChannel__SendMsg", 0 != rv)) {
949 0 : NaClLog(LOG_FATAL,
950 : "NaClSetUpBootstrapChannel: SendMsg failed, rv = %"NACL_PRIdS"\n",
951 : rv);
952 0 : }
953 10 : }
954 :
955 6 : NaClErrorCode NaClWaitForLoadModuleCommand(struct NaClApp *nap) {
956 6 : NaClErrorCode status;
957 :
958 6 : NaClLog(4, "NaClWaitForLoadModuleCommand started\n");
959 6 : NaClXMutexLock(&nap->mu);
960 24 : while (nap->module_initialization_state < NACL_MODULE_LOADED) {
961 12 : NaClXCondVarWait(&nap->cv, &nap->mu);
962 12 : }
963 6 : status = nap->module_load_status;
964 6 : NaClXMutexUnlock(&nap->mu);
965 6 : NaClLog(4, "NaClWaitForLoadModuleCommand finished\n");
966 :
967 6 : return status;
968 : }
969 :
970 259 : NaClErrorCode NaClWaitForLoadModuleStatus(struct NaClApp *nap) {
971 259 : NaClErrorCode status;
972 :
973 259 : NaClLog(4, "NaClWaitForLoadModuleStatus started\n");
974 259 : NaClXMutexLock(&nap->mu);
975 518 : while (LOAD_STATUS_UNKNOWN == (status = nap->module_load_status)) {
976 0 : NaClXCondVarWait(&nap->cv, &nap->mu);
977 0 : }
978 259 : NaClXMutexUnlock(&nap->mu);
979 259 : NaClLog(4, "NaClWaitForLoadModuleStatus finished\n");
980 :
981 259 : return status;
982 : }
983 :
984 265 : NaClErrorCode NaClWaitForStartModuleCommand(struct NaClApp *nap) {
985 265 : NaClErrorCode status;
986 :
987 265 : NaClLog(4, "NaClWaitForStartModuleCommand started\n");
988 265 : NaClXMutexLock(&nap->mu);
989 550 : while (nap->module_initialization_state < NACL_MODULE_STARTED) {
990 20 : NaClXCondVarWait(&nap->cv, &nap->mu);
991 20 : }
992 265 : status = nap->module_load_status;
993 265 : NaClXMutexUnlock(&nap->mu);
994 265 : NaClLog(4, "NaClWaitForStartModuleCommand finished\n");
995 :
996 265 : return status;
997 : }
998 :
999 7 : void NaClBlockIfCommandChannelExists(struct NaClApp *nap) {
1000 7 : if (NULL != nap->secure_service) {
1001 0 : for (;;) {
1002 0 : struct nacl_abi_timespec req;
1003 0 : req.tv_sec = 1000;
1004 0 : req.tv_nsec = 0;
1005 0 : NaClNanosleep(&req, (struct nacl_abi_timespec *) NULL);
1006 0 : }
1007 : }
1008 7 : }
1009 :
1010 10 : void NaClSecureCommandChannel(struct NaClApp *nap) {
1011 10 : struct NaClSecureService *secure_command_server;
1012 :
1013 10 : NaClLog(4, "Entered NaClSecureCommandChannel\n");
1014 :
1015 10 : secure_command_server = (struct NaClSecureService *) malloc(
1016 : sizeof *secure_command_server);
1017 20 : if (NACL_FI_ERROR_COND("NaClSecureCommandChannel__malloc",
1018 : NULL == secure_command_server)) {
1019 0 : NaClLog(LOG_FATAL, "Out of memory for secure command channel\n");
1020 0 : }
1021 20 : if (NACL_FI_ERROR_COND("NaClSecureCommandChannel__NaClSecureServiceCtor",
1022 : !NaClSecureServiceCtor(secure_command_server,
1023 : nap,
1024 : nap->secure_service_port,
1025 : nap->secure_service_address))) {
1026 0 : NaClLog(LOG_FATAL, "NaClSecureServiceCtor failed\n");
1027 0 : }
1028 10 : nap->secure_service = secure_command_server;
1029 :
1030 10 : NaClLog(4, "NaClSecureCommandChannel: starting service thread\n");
1031 20 : if (NACL_FI_ERROR_COND(
1032 : "NaClSecureCommandChannel__NaClSimpleServiceStartServiceThread",
1033 : !NaClSimpleServiceStartServiceThread((struct NaClSimpleService *)
1034 : secure_command_server))) {
1035 0 : NaClLog(LOG_FATAL,
1036 : "Could not start secure command channel service thread\n");
1037 0 : }
1038 :
1039 10 : NaClLog(4, "Leaving NaClSecureCommandChannel\n");
1040 10 : }
1041 :
1042 :
1043 271 : void NaClAppLoadModule(struct NaClApp *nap,
1044 271 : struct NaClDesc *nexe,
1045 271 : void (*load_cb)(void *instance_data,
1046 : NaClErrorCode status),
1047 271 : void *instance_data) {
1048 271 : NaClErrorCode status = LOAD_OK;
1049 :
1050 271 : NaClLog(4,
1051 : ("Entered NaClAppLoadModule: nap 0x%"NACL_PRIxPTR","
1052 : " nexe 0x%"NACL_PRIxPTR"\n"),
1053 : (uintptr_t) nap, (uintptr_t) nexe);
1054 : /*
1055 : * Ref was passed by value into |nexe| parameter, so up the refcount.
1056 : * Be sure to unref when the parameter's copy goes out of scope
1057 : * (when returning).
1058 : */
1059 271 : NaClDescRef(nexe);
1060 :
1061 : /*
1062 : * TODO(bsy): consider doing the processing below after sending the
1063 : * RPC reply to increase parallelism.
1064 : */
1065 271 : NaClXMutexLock(&nap->mu);
1066 271 : if (nap->module_initialization_state != NACL_MODULE_UNINITIALIZED) {
1067 0 : NaClLog(LOG_ERROR, "NaClAppLoadModule: repeated invocation\n");
1068 0 : status = LOAD_DUP_LOAD_MODULE;
1069 0 : NaClXMutexUnlock(&nap->mu);
1070 0 : if (NULL != load_cb) {
1071 0 : (*load_cb)(instance_data, status);
1072 0 : }
1073 0 : NaClDescUnref(nexe);
1074 0 : return;
1075 : }
1076 271 : nap->module_initialization_state = NACL_MODULE_LOADING;
1077 271 : NaClXCondVarBroadcast(&nap->cv);
1078 271 : NaClXMutexUnlock(&nap->mu);
1079 :
1080 271 : if (NULL != load_cb) {
1081 8 : (*load_cb)(instance_data, status);
1082 8 : }
1083 :
1084 271 : NaClXMutexLock(&nap->mu);
1085 :
1086 : /*
1087 : * Check and possibly mark the nexe binary as OK to attempt memory
1088 : * mapping. We first clear the safe-for-mmap flag -- if we do not
1089 : * trust the renderer to really send us a safe-to-mmap descriptor
1090 : * and have to query the validation cache, then we also do not want
1091 : * to trust the metadata flag value that originated from the
1092 : * renderer.
1093 : */
1094 271 : NaClDescMarkUnsafeForMmap(nexe);
1095 271 : NaClReplaceDescIfValidationCacheAssertsMappable(&nexe,
1096 : nap->validation_cache);
1097 : /* Transfer ownership from nexe to nap->main_nexe_desc. */
1098 813 : CHECK(nap->main_nexe_desc == NULL);
1099 271 : nap->main_nexe_desc = nexe;
1100 271 : nexe = NULL;
1101 :
1102 811 : status = NACL_FI_VAL("load_module", NaClErrorCode,
1103 : NaClAppLoadFile(nap->main_nexe_desc, nap));
1104 :
1105 269 : if (LOAD_OK != status) {
1106 6 : nap->module_load_status = status;
1107 6 : nap->module_initialization_state = NACL_MODULE_ERROR;
1108 6 : NaClXCondVarBroadcast(&nap->cv);
1109 6 : }
1110 269 : NaClXMutexUnlock(&nap->mu); /* NaClAppPrepareToLaunch takes mu */
1111 269 : if (LOAD_OK != status) {
1112 6 : NaClDescUnref(nap->main_nexe_desc);
1113 6 : nap->main_nexe_desc = NULL;
1114 6 : return;
1115 : }
1116 :
1117 : /***************************************************************************
1118 : * TODO(bsy): Remove/merge the code invoking NaClAppPrepareToLaunch
1119 : * and NaClGdbHook below with sel_main's main function. See comment
1120 : * there.
1121 : ***************************************************************************/
1122 :
1123 : /*
1124 : * Finish setting up the NaCl App.
1125 : */
1126 263 : status = NaClAppPrepareToLaunch(nap);
1127 :
1128 263 : NaClXMutexLock(&nap->mu);
1129 263 : nap->module_load_status = status;
1130 263 : nap->module_initialization_state = NACL_MODULE_LOADED;
1131 263 : NaClXCondVarBroadcast(&nap->cv);
1132 263 : NaClXMutexUnlock(&nap->mu);
1133 :
1134 : /* Give debuggers a well known point at which xlate_base is known. */
1135 263 : NaClGdbHook(nap);
1136 532 : }
1137 :
1138 3 : int NaClAppRuntimeHostSetup(struct NaClApp *nap,
1139 3 : struct NaClRuntimeHostInterface *host_itf) {
1140 3 : NaClErrorCode status = LOAD_OK;
1141 :
1142 3 : NaClLog(4,
1143 : ("Entered NaClAppRuntimeHostSetup, nap 0x%"NACL_PRIxPTR","
1144 : " host_itf 0x%"NACL_PRIxPTR"\n"),
1145 : (uintptr_t) nap, (uintptr_t) host_itf);
1146 :
1147 3 : NaClXMutexLock(&nap->mu);
1148 3 : if (nap->module_initialization_state > NACL_MODULE_STARTING) {
1149 0 : NaClLog(LOG_ERROR, "NaClAppRuntimeHostSetup: too late\n");
1150 0 : status = LOAD_INTERNAL;
1151 0 : goto cleanup_status_mu;
1152 : }
1153 :
1154 : nap->runtime_host_interface = (struct NaClRuntimeHostInterface *)
1155 3 : NaClRefCountRef((struct NaClRefCount *) host_itf);
1156 :
1157 : /*
1158 : * Hook up runtime host enabled resources, e.g.,
1159 : * DEBUG_ONLY:dev://postmessage. NB: Resources specified by
1160 : * file:path should have been taken care of earlier, in
1161 : * NaClAppInitialDescriptorHookup.
1162 : */
1163 3 : nap->resource_phase = NACL_RESOURCE_PHASE_RUNTIME_HOST;
1164 3 : NaClLog(4, "Processing dev I/O redirection/inheritance from environment\n");
1165 3 : NaClProcessRedirControl(nap);
1166 3 : NaClLog(4, "... done.\n");
1167 :
1168 : cleanup_status_mu:
1169 3 : NaClXMutexUnlock(&nap->mu);
1170 3 : return (int) status;
1171 : }
1172 :
1173 3 : int NaClAppDescQuotaSetup(struct NaClApp *nap,
1174 3 : struct NaClDescQuotaInterface *quota_itf) {
1175 3 : NaClErrorCode status = LOAD_OK;
1176 :
1177 3 : NaClLog(4,
1178 : ("Entered NaClAppDescQuotaSetup, nap 0x%"NACL_PRIxPTR","
1179 : " quota_itf 0x%"NACL_PRIxPTR"\n"),
1180 : (uintptr_t) nap, (uintptr_t) quota_itf);
1181 :
1182 3 : NaClXMutexLock(&nap->mu);
1183 3 : if (nap->module_initialization_state > NACL_MODULE_STARTING) {
1184 0 : NaClLog(LOG_ERROR, "NaClAppDescQuotaSetup: too late\n");
1185 0 : status = LOAD_INTERNAL;
1186 0 : goto cleanup_status_mu;
1187 : }
1188 :
1189 : nap->desc_quota_interface = (struct NaClDescQuotaInterface *)
1190 3 : NaClRefCountRef((struct NaClRefCount *) quota_itf);
1191 :
1192 : cleanup_status_mu:
1193 3 : NaClXMutexUnlock(&nap->mu);
1194 3 : return (int) status;
1195 : }
1196 :
1197 262 : void NaClAppStartModule(struct NaClApp *nap,
1198 262 : void (*start_cb)(void *instance_data,
1199 : NaClErrorCode status),
1200 262 : void *instance_data) {
1201 262 : NaClErrorCode status;
1202 :
1203 262 : NaClLog(4,
1204 : ("Entered NaClAppStartModule, nap 0x%"NACL_PRIxPTR","
1205 : " start_cb 0x%"NACL_PRIxPTR", instance_data 0x%"NACL_PRIxPTR"\n"),
1206 : (uintptr_t) nap, (uintptr_t) start_cb, (uintptr_t) instance_data);
1207 :
1208 : /*
1209 : * When module is loading, we have to block and wait till it is
1210 : * fully loaded before we can proceed with start module.
1211 : */
1212 262 : NaClXMutexLock(&nap->mu);
1213 262 : if (NACL_MODULE_LOADING == nap->module_initialization_state) {
1214 0 : while (NACL_MODULE_LOADED != nap->module_initialization_state) {
1215 0 : NaClXCondVarWait(&nap->cv, &nap->mu);
1216 0 : }
1217 0 : }
1218 262 : if (nap->module_initialization_state != NACL_MODULE_LOADED) {
1219 7 : if (NACL_MODULE_ERROR == nap->module_initialization_state) {
1220 6 : NaClLog(LOG_ERROR, "NaClAppStartModule: error loading module\n");
1221 6 : status = nap->module_load_status;
1222 7 : } else if (nap->module_initialization_state > NACL_MODULE_LOADED) {
1223 0 : NaClLog(LOG_ERROR, "NaClAppStartModule: repeated invocation\n");
1224 0 : status = LOAD_DUP_START_MODULE;
1225 1 : } else if (nap->module_initialization_state < NACL_MODULE_LOADED) {
1226 1 : NaClLog(LOG_ERROR, "NaClAppStartModule: module not loaded\n");
1227 1 : status = LOAD_INTERNAL;
1228 1 : }
1229 7 : NaClXMutexUnlock(&nap->mu);
1230 7 : if (NULL != start_cb) {
1231 0 : (*start_cb)(instance_data, status);
1232 0 : }
1233 7 : return;
1234 : }
1235 255 : status = nap->module_load_status;
1236 255 : nap->module_initialization_state = NACL_MODULE_STARTING;
1237 255 : NaClXCondVarBroadcast(&nap->cv);
1238 255 : NaClXMutexUnlock(&nap->mu);
1239 :
1240 255 : NaClLog(4, "NaClSecureChannelStartModule: load status %d\n", status);
1241 :
1242 : /*
1243 : * We need to invoke the callback now, before we signal the main thread
1244 : * to possibly start by setting the state to NACL_MODULE_STARTED, since
1245 : * in the case of failure the main thread may quickly exit; if the main
1246 : * thread does this before we sent the reply, than the plugin (or any
1247 : * other runtime host interface) will be left without an aswer. The
1248 : * NACL_MODULE_STARTING state is used as an intermediate state to prevent
1249 : * double invocations violating the protocol.
1250 : */
1251 255 : if (NULL != start_cb) {
1252 10 : (*start_cb)(instance_data, status);
1253 10 : }
1254 :
1255 255 : NaClXMutexLock(&nap->mu);
1256 255 : nap->module_initialization_state = NACL_MODULE_STARTED;
1257 255 : NaClXCondVarBroadcast(&nap->cv);
1258 255 : NaClXMutexUnlock(&nap->mu);
1259 517 : }
1260 :
1261 5 : void NaClAppShutdown(struct NaClApp *nap,
1262 5 : int exit_status) {
1263 5 : NaClLog(4, "NaClAppShutdown: nap 0x%"NACL_PRIxPTR
1264 : ", exit_status %d\n", (uintptr_t) nap, exit_status);
1265 :
1266 5 : NaClXMutexLock(&nap->mu);
1267 5 : nap->exit_status = exit_status;
1268 5 : NaClXMutexUnlock(&nap->mu);
1269 5 : if (NULL != nap->debug_stub_callbacks) {
1270 0 : nap->debug_stub_callbacks->process_exit_hook();
1271 0 : }
1272 5 : NaClExit(0);
1273 5 : }
1274 :
1275 : /*
1276 : * It is fine to have multiple I/O operations read from memory in Write
1277 : * or SendMsg like operations.
1278 : */
1279 91581 : void NaClVmIoWillStart(struct NaClApp *nap,
1280 91581 : uint32_t addr_first_usr,
1281 91581 : uint32_t addr_last_usr) {
1282 91581 : NaClXMutexLock(&nap->mu);
1283 91581 : (*nap->mem_io_regions->vtbl->AddInterval)(nap->mem_io_regions,
1284 : addr_first_usr,
1285 : addr_last_usr);
1286 91581 : NaClXMutexUnlock(&nap->mu);
1287 91581 : }
1288 :
1289 :
1290 91579 : void NaClVmIoHasEnded(struct NaClApp *nap,
1291 91579 : uint32_t addr_first_usr,
1292 91579 : uint32_t addr_last_usr) {
1293 91579 : NaClXMutexLock(&nap->mu);
1294 91579 : (*nap->mem_io_regions->vtbl->RemoveInterval)(nap->mem_io_regions,
1295 : addr_first_usr,
1296 : addr_last_usr);
1297 91579 : NaClXMutexUnlock(&nap->mu);
1298 91579 : }
1299 :
1300 139804 : void NaClVmIoPendingCheck_mu(struct NaClApp *nap,
1301 139804 : uint32_t addr_first_usr,
1302 139804 : uint32_t addr_last_usr) {
1303 139804 : if ((*nap->mem_io_regions->vtbl->OverlapsWith)(nap->mem_io_regions,
1304 : addr_first_usr,
1305 : addr_last_usr)) {
1306 2 : NaClLog(LOG_FATAL,
1307 : "NaClVmIoWillStart: program mem write race detected. ABORTING\n");
1308 2 : }
1309 139802 : }
1310 :
1311 : /*
1312 : * GDB's canonical overlay managment routine.
1313 : * We need its symbol in the symbol table so don't inline it.
1314 : * TODO(dje): add some explanation for the non-GDB person.
1315 : */
1316 : #if NACL_WINDOWS
1317 : __declspec(dllexport noinline)
1318 : #endif
1319 : #ifdef __GNUC__
1320 : __attribute__((noinline))
1321 : #endif
1322 : void _ovly_debug_event (void) {
1323 : #ifdef __GNUC__
1324 : /*
1325 : * The asm volatile is here as instructed by the GCC docs.
1326 : * It's not enough to declare a function noinline.
1327 : * GCC will still look inside the function to see if it's worth calling.
1328 : */
1329 267 : __asm__ volatile ("");
1330 : #elif NACL_WINDOWS
1331 : /*
1332 : * Visual Studio inlines empty functions even with noinline attribute,
1333 : * so we need a compile memory barrier to make this function not to be
1334 : * inlined. Also, it guarantees that nacl_global_xlate_base initialization
1335 : * is not reordered. This is important for gdb since it sets breakpoint on
1336 : * this function and reads nacl_global_xlate_base value.
1337 : */
1338 : _ReadWriteBarrier();
1339 : #endif
1340 267 : }
1341 :
1342 267 : static void StopForDebuggerInit (uintptr_t mem_start) {
1343 : /* Put xlate_base in a place where gdb can find it. */
1344 267 : nacl_global_xlate_base = mem_start;
1345 :
1346 267 : NaClSandboxMemoryStartForValgrind(mem_start);
1347 :
1348 267 : _ovly_debug_event();
1349 267 : }
1350 :
1351 267 : void NaClGdbHook(struct NaClApp const *nap) {
1352 267 : StopForDebuggerInit(nap->mem_start);
1353 267 : }
|