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 : /*
8 : * NaCl Simple/secure ELF loader (NaCl SEL).
9 : *
10 : * This loader can only process NaCl object files as produced using
11 : * the NaCl toolchain. Other ELF files will be rejected.
12 : *
13 : * The primary function, NaClAppLoadFile, parses an ELF file,
14 : * allocates memory, loads the relocatable image from the ELF file
15 : * into memory, and performs relocation. NaClAppRun runs the
16 : * resultant program.
17 : *
18 : * This loader is written in C so that it can be used by C-only as
19 : * well as C++ applications. Other languages should also be able to
20 : * use their foreign-function interfaces to invoke C code.
21 : *
22 : * This loader must be part of the NaCl TCB, since it directly handles
23 : * externally supplied input (the ELF file). Any security
24 : * vulnerabilities in handling the ELF image, e.g., buffer or integer
25 : * overflows, can put the application at risk.
26 : */
27 :
28 : #ifndef NATIVE_CLIENT_SRC_TRUSTED_SERVICE_RUNTIME_SEL_LDR_H_
29 : #define NATIVE_CLIENT_SRC_TRUSTED_SERVICE_RUNTIME_SEL_LDR_H_ 1
30 :
31 : #include "native_client/src/include/atomic_ops.h"
32 : #include "native_client/src/include/nacl_base.h"
33 : #include "native_client/src/include/portability.h"
34 : #include "native_client/src/include/elf.h"
35 :
36 : #include "native_client/src/public/nacl_app.h"
37 :
38 : #include "native_client/src/shared/platform/nacl_host_desc.h"
39 : #include "native_client/src/shared/platform/nacl_log.h"
40 : #include "native_client/src/shared/platform/nacl_threads.h"
41 :
42 : #include "native_client/src/shared/srpc/nacl_srpc.h"
43 :
44 : #include "native_client/src/trusted/interval_multiset/nacl_interval_multiset.h"
45 : #include "native_client/src/trusted/interval_multiset/nacl_interval_range_tree.h"
46 :
47 : #include "native_client/src/trusted/service_runtime/dyn_array.h"
48 : #include "native_client/src/trusted/service_runtime/nacl_error_code.h"
49 : #include "native_client/src/trusted/service_runtime/nacl_kernel_service.h"
50 : #include "native_client/src/trusted/service_runtime/nacl_resource.h"
51 : #include "native_client/src/trusted/service_runtime/nacl_secure_service.h"
52 : #include "native_client/src/trusted/service_runtime/name_service/name_service.h"
53 : #include "native_client/src/trusted/service_runtime/sel_addrspace.h"
54 : #include "native_client/src/trusted/service_runtime/sel_mem.h"
55 : #include "native_client/src/trusted/service_runtime/sel_rt.h"
56 : #include "native_client/src/trusted/service_runtime/sel_util.h"
57 : #include "native_client/src/trusted/service_runtime/sys_futex.h"
58 :
59 : #include "native_client/src/trusted/validator/ncvalidate.h"
60 :
61 : EXTERN_C_BEGIN
62 :
63 : #define NACL_SERVICE_PORT_DESCRIPTOR 3
64 : #define NACL_SERVICE_ADDRESS_DESCRIPTOR 4
65 :
66 : #define NACL_DEFAULT_STACK_MAX (16 << 20) /* main thread stack */
67 :
68 : struct NaClAppThread;
69 : struct NaClDesc; /* see native_client/src/trusted/desc/nacl_desc_base.h */
70 : struct NaClDynamicRegion;
71 : struct NaClRuntimeHostInterface;
72 : struct NaClDescQuotaInterface;
73 : struct NaClSignalContext;
74 : struct NaClThreadInterface; /* see sel_ldr_thread_interface.h */
75 : struct NaClValidationCache;
76 : struct NaClValidationMetadata;
77 :
78 : struct NaClDebugCallbacks {
79 : void (*thread_create_hook)(struct NaClAppThread *natp);
80 : void (*thread_exit_hook)(struct NaClAppThread *natp);
81 : void (*process_exit_hook)(void);
82 : };
83 :
84 : enum NaClResourcePhase {
85 : NACL_RESOURCE_PHASE_START,
86 : NACL_RESOURCE_PHASE_RUNTIME_HOST
87 : };
88 :
89 : #if NACL_WINDOWS
90 : enum NaClDebugExceptionHandlerState {
91 : NACL_DEBUG_EXCEPTION_HANDLER_NOT_STARTED,
92 : NACL_DEBUG_EXCEPTION_HANDLER_STARTED,
93 : NACL_DEBUG_EXCEPTION_HANDLER_FAILED
94 : };
95 : /*
96 : * Callback function used to request that an exception handler be
97 : * attached using the Windows debug API. See sel_main_chrome.h.
98 : */
99 : typedef int (*NaClAttachDebugExceptionHandlerFunc)(const void *info,
100 : size_t size);
101 : #endif
102 :
103 : struct NaClSpringboardInfo {
104 : /* These are addresses in untrusted address space (relative to mem_start). */
105 : uint32_t start_addr;
106 : uint32_t end_addr;
107 : };
108 :
109 : struct NaClApp {
110 : /*
111 : * public, user settable prior to app start.
112 : */
113 : uint8_t addr_bits;
114 : uintptr_t stack_size;
115 : uint32_t initial_nexe_max_code_bytes;
116 : /*
117 : * stack_size is the maximum size of the (main) stack. The stack
118 : * memory is eager allocated (mapped in w/o MAP_NORESERVE) so
119 : * there must be enough swap space; page table entries are not
120 : * populated (no MAP_POPULATE), so actual accesses will likely
121 : * incur page faults.
122 : */
123 :
124 : /*
125 : * Determined at load time; OS-determined.
126 : * Read-only after load, so accesses do not require locking.
127 : */
128 : uintptr_t mem_start;
129 :
130 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
131 : uintptr_t pcrel_thunk;
132 : uintptr_t pcrel_thunk_end;
133 : #endif
134 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
135 : uintptr_t nacl_syscall_addr;
136 : uintptr_t get_tls_fast_path1_addr;
137 : uintptr_t get_tls_fast_path2_addr;
138 : #endif
139 :
140 : /* only used for ET_EXEC: for CS restriction */
141 : uintptr_t static_text_end;
142 : /*
143 : * relative to mem_start; ro after app starts. memsz from phdr
144 : */
145 :
146 : /*
147 : * The dynamic code area follows the static code area. These fields
148 : * are both set to static_text_end if the dynamic code area has zero
149 : * size.
150 : */
151 : uintptr_t dynamic_text_start;
152 : uintptr_t dynamic_text_end;
153 :
154 : /*
155 : * rodata_start and data_start may be 0 if these segments are not
156 : * present in the executable.
157 : */
158 : uintptr_t rodata_start; /* initialized data, ro */
159 : uintptr_t data_start; /* initialized data/bss, rw */
160 : /*
161 : * Various region sizes must be a multiple of NACL_MAP_PAGESIZE
162 : * before the NaCl app can run. The sizes from the ELF file
163 : * (p_filesz field) might not be -- that would waste space for
164 : * padding -- and while we could use p_memsz to specify padding, but
165 : * we will record the virtual addresses of the start of the segments
166 : * and figure out the gap between the p_vaddr + p_filesz of one
167 : * segment and p_vaddr of the next to determine padding.
168 : */
169 :
170 : uintptr_t data_end;
171 : /* see break_addr below */
172 :
173 : /*
174 : * initial_entry_pt is the first address in untrusted code to jump
175 : * to. When using the IRT (integrated runtime), this is provided by
176 : * the IRT library, and user_entry_pt is the entry point in the user
177 : * executable. Otherwise, initial_entry_pt is in the user
178 : * executable and user_entry_pt is zero.
179 : */
180 : uintptr_t initial_entry_pt;
181 : uintptr_t user_entry_pt;
182 :
183 : /*
184 : * bundle_size is the bundle alignment boundary for validation (16
185 : * or 32), so int is okay. This value must be a power of 2.
186 : */
187 : int bundle_size;
188 :
189 : /* common to both ELF executables and relocatable load images */
190 :
191 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
192 : /* Addresses of trusted springboard code for switching to untrusted code. */
193 : struct NaClSpringboardInfo syscall_return_springboard;
194 : struct NaClSpringboardInfo all_regs_springboard;
195 : #endif
196 :
197 : /*
198 : * The socket at which the app should be accepting connections. The
199 : * corresponding socket address are made available by the JavaScript
200 : * bridge to other NaCl modules.
201 : */
202 : struct NaClDesc *service_port;
203 : struct NaClDesc *service_address;
204 :
205 : struct NaClDesc *secure_service_port;
206 : struct NaClDesc *secure_service_address;
207 :
208 : struct NaClDesc *bootstrap_channel;
209 :
210 : /*
211 : * The IRT may be supplied by an SRPC call via the command channel,
212 : * or by the irt_fd member in struct NaClChromeMainArgs in the case
213 : * of sel_main_chrome (the embedded service runtime), or by the -B
214 : * command line argument in the case of sel_main (the standalone
215 : * service runtime process). We let the command channel have
216 : * priority.
217 : */
218 : int irt_loaded; /* bool */
219 :
220 : /*
221 : * The main NaCl executable may already be validated during ELF
222 : * loading, where after a validation cache hit the code gets mmapped
223 : * into memory if the file descriptor is "blessed" as referring to a
224 : * file which the embedding environment guarantees to be effectively
225 : * immutable. If it did not validate or the file descriptor is not
226 : * blessed, then the code is read into memory, and we will validate
227 : * it later in the code path, in NaClAppLoadFileAslr.
228 : */
229 : int main_exe_prevalidated; /* bool */
230 :
231 : struct NaClMutex mu;
232 : struct NaClCondVar cv;
233 :
234 : #if NACL_WINDOWS
235 : /*
236 : * invariant: !(vm_hole_may_exist && threads_launching != 0).
237 : * vm_hole_may_exist is set while mmap/munmap manipulates the memory
238 : * map, and threads_launching is set while a thread is launching
239 : * (and a trusted thread stack is being allocated).
240 : *
241 : * strictly speaking, vm_hole_may_exist need not be present, since
242 : * the vm code ensures that 0 == threads_launching and then holds
243 : * the lock for the duration of the VM operation. it is safer this
244 : * way, in case we later introduce code that might want to
245 : * temporarily drop the process lock.
246 : */
247 : int vm_hole_may_exist;
248 : int threads_launching;
249 : #endif
250 :
251 : /*
252 : * An array of NaCl syscall handlers. The length of the array must be
253 : * at least NACL_MAX_SYSCALLS.
254 : */
255 : struct NaClSyscallTableEntry *syscall_table;
256 :
257 : /*
258 : * Name service must launch after mu, cv, vm_hole_may_exit,
259 : * threads_launching are initialized.
260 : */
261 : struct NaClNameService *name_service; /* default name server */
262 : struct NaClDesc *name_service_conn_cap;
263 :
264 : struct NaClSecureService *secure_service;
265 :
266 : struct NaClKernelService *kernel_service;
267 :
268 : struct NaClResourceNaClApp resources;
269 : enum NaClResourcePhase resource_phase;
270 :
271 : struct NaClRuntimeHostInterface *runtime_host_interface;
272 : struct NaClDescQuotaInterface *desc_quota_interface;
273 :
274 : /*
275 : * The ordering in this enum is important. We use the ordering
276 : * to check that the status of module initialization; the state
277 : * is really being used as a state machine. Please do not change
278 : * the ordering, if you need to add a new state please do so at
279 : * the appropriate position dependending on a module loading phase.
280 : */
281 :
282 : enum NaClModuleInitializationState {
283 : NACL_MODULE_UNINITIALIZED = 0,
284 : NACL_MODULE_LOADING,
285 : NACL_MODULE_LOADED,
286 : NACL_MODULE_STARTING,
287 : NACL_MODULE_STARTED,
288 : NACL_MODULE_ERROR
289 : } module_initialization_state;
290 : NaClErrorCode module_load_status;
291 :
292 : /*
293 : * runtime info below, thread state, etc; initialized only when app
294 : * is run. Mutex mu protects access to mem_map and other member
295 : * variables while the application is running and may be
296 : * multithreaded; thread, desc members have their own locks. At
297 : * other times it is assumed that only one thread is
298 : * constructing/loading the NaClApp and that no mutual exclusion is
299 : * needed.
300 : */
301 :
302 : /*
303 : * memory map is in user addresses.
304 : */
305 : struct NaClVmmap mem_map;
306 :
307 : struct NaClIntervalMultiset *mem_io_regions;
308 :
309 : /*
310 : * This is the effector interface object that is used to manipulate
311 : * NaCl apps by the objects in the NaClDesc class hierarchy. This
312 : * is used by this NaClApp when making NaClDesc method calls from
313 : * syscall handlers. Currently, this is when NaClDesc objects need
314 : * to manipulate the untrusted address space -- the mmap
315 : * implementation need to unmap the untrusted pages, and on Windows
316 : * this requires different calls depending on how the pages were
317 : * created.
318 : */
319 : struct NaClDescEffector *effp;
320 :
321 : /*
322 : * may reject nexes that are incompatible w/ dynamic-text in the near future
323 : */
324 : int enable_dyncode_syscalls;
325 : int use_shm_for_dynamic_text;
326 : struct NaClDesc *text_shm;
327 : struct NaClMutex dynamic_load_mutex;
328 : /*
329 : * This records which pages in text_shm have been allocated. When a
330 : * page is allocated, it is filled with halt instructions and then
331 : * made executable by untrusted code.
332 : */
333 : uint8_t *dynamic_page_bitmap;
334 :
335 : /*
336 : * The array of dynamic_regions is maintained in sorted order
337 : * Accesses must be protected by dynamic_load_mutex.
338 : */
339 : struct NaClDynamicRegion *dynamic_regions;
340 : int num_dynamic_regions;
341 : int dynamic_regions_allocated;
342 :
343 : /*
344 : * These variables are used for caching mapped writable views of the
345 : * dynamic text segment. See CachedMapWritableText in nacl_text.c.
346 : * Accesses must be protected by dynamic_load_mutex
347 : */
348 : uint32_t dynamic_mapcache_offset;
349 : uint32_t dynamic_mapcache_size;
350 : uintptr_t dynamic_mapcache_ret;
351 :
352 : /*
353 : * Monotonically increasing generation number used for deletion
354 : * Accesses must be protected by dynamic_load_mutex
355 : */
356 : int dynamic_delete_generation;
357 :
358 :
359 : int running;
360 : int exit_status;
361 :
362 : NaClCPUFeatures *cpu_features;
363 : int fixed_feature_cpu_mode;
364 : struct NaClValidationCache *validation_cache;
365 : int ignore_validator_result;
366 : int skip_validator;
367 : int validator_stub_out_mode;
368 :
369 : int enable_list_mappings;
370 : /* Whether or not the app is a PNaCl app. Boolean. */
371 : int pnacl_mode;
372 :
373 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
374 : uint16_t code_seg_sel;
375 : uint16_t data_seg_sel;
376 : #endif
377 :
378 : uintptr_t break_addr; /* user addr */
379 : /* data_end <= break_addr is an invariant */
380 :
381 : /*
382 : * Thread table lock threads_mu is higher in the locking order than
383 : * the thread locks, i.e., threads_mu must be acqured w/o holding
384 : * any per-thread lock (natp->mu).
385 : */
386 : struct NaClMutex threads_mu;
387 : struct DynArray threads; /* NaClAppThread pointers */
388 : int num_threads; /* number actually running */
389 :
390 : struct NaClFastMutex desc_mu;
391 : struct DynArray desc_tbl; /* NaClDesc pointers */
392 :
393 : const struct NaClDebugCallbacks *debug_stub_callbacks;
394 : #if NACL_WINDOWS
395 : uint16_t debug_stub_port;
396 : #endif
397 : struct NaClDesc *main_nexe_desc;
398 : struct NaClDesc *irt_nexe_desc;
399 :
400 : struct NaClMutex exception_mu;
401 : uint32_t exception_handler;
402 : int enable_exception_handling;
403 : #if NACL_WINDOWS
404 : enum NaClDebugExceptionHandlerState debug_exception_handler_state;
405 : NaClAttachDebugExceptionHandlerFunc attach_debug_exception_handler_func;
406 : #endif
407 : /*
408 : * enable_faulted_thread_queue is a boolean which enables handling
409 : * of untrusted faults which is used by the debug stub. When an
410 : * untrusted thread faults, it is blocked until
411 : * NaClAppThreadUnblockIfFaulted() is called on the thread.
412 : */
413 : int enable_faulted_thread_queue;
414 : /*
415 : * faulted_thread_count is the number of NaClAppThreads for which
416 : * fault_signal is non-zero.
417 : */
418 : Atomic32 faulted_thread_count;
419 : #if NACL_WINDOWS
420 : /*
421 : * An event that is signaled by debug exception handler process when it fills
422 : * fault_signal field with non-zero value for some NaClAppThread.
423 : */
424 : HANDLE faulted_thread_event;
425 : #else
426 : /*
427 : * A file descriptor of a pipe which becomes available for reading in
428 : * the event that fault_signal for some NaClAppThread becomes non-zero.
429 : */
430 : int faulted_thread_fd_read;
431 : int faulted_thread_fd_write;
432 : #endif
433 :
434 : /*
435 : * Cache of sysconf(_SC_NPROCESSORS_ONLN) (or equivalent) result.
436 : */
437 : int sc_nprocessors_onln;
438 :
439 : const struct NaClValidatorInterface *validator;
440 :
441 : /*
442 : * Mutex for protecting futex_wait_list_head. Lock ordering:
443 : * NaClApp::mu may be claimed after futex_wait_list_mu but never
444 : * before it.
445 : */
446 : struct NaClMutex futex_wait_list_mu;
447 : /*
448 : * This is the sentinel node for a doubly linked list of
449 : * NaClAppThreads. This lists the threads that are waiting to be
450 : * woken up by futex_wake(). This list must only be accessed while
451 : * holding the mutex futex_wait_list_mu.
452 : */
453 : struct NaClListNode futex_wait_list_head;
454 : };
455 :
456 :
457 :
458 : void NaClAppIncrVerbosity(void);
459 :
460 : /*
461 : * Initializes a NaCl application with the default parameters
462 : * and the specified syscall table.
463 : *
464 : * If invoked after the outer sandbox is enabled, the caller is
465 : * responsible for initializing the sc_nprocessors_onln member to a
466 : * sane value.
467 : *
468 : * nap is a pointer to the NaCl object that is being filled in.
469 : *
470 : * table is the NaCl syscall table. The syscall table must contain at least
471 : * NACL_MAX_SYSCALLS valid entries.
472 : *
473 : * Caution! Syscall handlers must be extremely careful with respect to
474 : * argument validation, including time-of-check vs time-of-use defense, etc.
475 : */
476 : int NaClAppWithSyscallTableCtor(struct NaClApp *nap,
477 : struct NaClSyscallTableEntry *table) NACL_WUR;
478 : /*
479 : * Standard Ctor for NaClApp objects. Installs default syscall
480 : * handlers.
481 : *
482 : * If invoked after the outer sandbox is enabled, the caller is
483 : * responsible for initializing the sc_nprocessors_onln member to a
484 : * sane value.
485 : *
486 : * nap is a pointer to the NaCl object that is being filled in.
487 : */
488 : int NaClAppCtor(struct NaClApp *nap) NACL_WUR;
489 :
490 : /*
491 : * Loads a NaCl ELF file into memory in preparation for running it.
492 : *
493 : * gp is a pointer to a generic I/O object and should be a GioMem with
494 : * a memory buffer containing the file read entirely into memory if
495 : * the file system might be subject to race conditions (e.g., another
496 : * thread / process might modify a downloaded NaCl ELF file while we
497 : * are loading it here).
498 : *
499 : * nap is a pointer to the NaCl object that is being filled in. it
500 : * should be properly constructed via NaClAppCtor.
501 : *
502 : * return value: one of the LOAD_* values defined in
503 : * nacl_error_code.h. TODO: add some error detail string and hang
504 : * that off the nap object, so that more details are available w/o
505 : * incrementing verbosity (and polluting stdout).
506 : *
507 : * note: it may be necessary to flush the icache if the memory
508 : * allocated for use had already made it into the icache from another
509 : * NaCl application instance, and the icache does not detect
510 : * self-modifying code / data writes and automatically invalidate the
511 : * cache lines.
512 : */
513 : NaClErrorCode NaClAppLoadFile(struct NaClDesc *ndp,
514 : struct NaClApp *nap) NACL_WUR;
515 :
516 : /*
517 : * Just like NaClAppLoadFile, but allow control over ASLR.
518 : */
519 : NaClErrorCode NaClAppLoadFileAslr(struct NaClDesc *ndp,
520 : struct NaClApp *nap,
521 : enum NaClAslrMode aslr_mode) NACL_WUR;
522 :
523 :
524 : NaClErrorCode NaClAppLoadFileDynamically(
525 : struct NaClApp *nap,
526 : struct NaClDesc *ndp,
527 : struct NaClValidationMetadata *metadata) NACL_WUR;
528 :
529 : void NaClAppPrintDetails(struct NaClApp *nap,
530 : struct Gio *gp);
531 :
532 : NaClErrorCode NaClLoadImage(struct Gio *gp,
533 : struct NaClApp *nap) NACL_WUR;
534 :
535 : int NaClValidateCode(struct NaClApp *nap,
536 : uintptr_t guest_addr,
537 : uint8_t *data,
538 : size_t size,
539 : const struct NaClValidationMetadata *metadata) NACL_WUR;
540 :
541 : /*
542 : * Validates that the code found at data_old can safely be replaced with
543 : * the code found at data_new.
544 : */
545 : int NaClValidateCodeReplacement(struct NaClApp *nap,
546 : uintptr_t guest_addr,
547 : uint8_t *data_old,
548 : uint8_t *data_new,
549 : size_t size);
550 :
551 : /*
552 : * Copies code from data_new to data_old in a thread-safe way.
553 : */
554 : int NaClCopyCode(struct NaClApp *nap, uintptr_t guest_addr,
555 : uint8_t *data_old, uint8_t *data_new,
556 : size_t size);
557 :
558 : /*
559 : * Copies an instruction in a thread-safe way. Used by validators.
560 : */
561 : int NaClCopyInstruction(uint8_t *dst, uint8_t *src, uint8_t sz);
562 :
563 : NaClErrorCode NaClValidateImage(struct NaClApp *nap) NACL_WUR;
564 :
565 :
566 : int NaClAddrIsValidEntryPt(struct NaClApp *nap,
567 : uintptr_t addr);
568 :
569 : /*
570 : * Takes ownership of descriptor, i.e., when NaCl app closes, it's gone.
571 : */
572 : void NaClAddHostDescriptor(struct NaClApp *nap,
573 : int host_os_desc,
574 : int mode,
575 : int nacl_desc);
576 :
577 : /*
578 : * Takes ownership of handle.
579 : */
580 : void NaClAddImcHandle(struct NaClApp *nap,
581 : NaClHandle h,
582 : int nacl_desc);
583 :
584 : /*
585 : * Launch system-level service threads. After this, access to the
586 : * NaClApp object must be done in a thread-safe manner, using nap->mu
587 : * etc, or access only read-only data.
588 : *
589 : * NB: the "secure command channel" thread should have already started
590 : * (if enabled); that thread must take care to not race with the main
591 : * thread that is continuing to set up the NaCl module as well.
592 : */
593 : int NaClAppLaunchServiceThreads(struct NaClApp *nap);
594 :
595 : /*
596 : * Report the low eight bits of |exit_status| via the reverse channel
597 : * in |nap|, if one exists, to whomever is interested. This usually
598 : * involves an RPC. Returns true if successfully reported.
599 : *
600 : * Also mark nap's exit_status and running member variables, announce
601 : * via condvar that the nexe should be considered no longer running.
602 : *
603 : * Returns true (non-zero) if exit status was reported via the reverse
604 : * channel, and false (0) otherwise.
605 : */
606 : int NaClReportExitStatus(struct NaClApp *nap, int exit_status);
607 :
608 : /*
609 : * Get the top of the initial thread's stack. Returns a user address.
610 : */
611 : uintptr_t NaClGetInitialStackTop(struct NaClApp *nap);
612 :
613 : /*
614 : * Used to launch the main thread. NB: calling thread may in the
615 : * future become the main NaCl app thread, and this function will
616 : * return only after the NaCl app main thread exits. In such an
617 : * alternative design, NaClWaitForMainThreadToExit will become a
618 : * no-op.
619 : */
620 : int NaClCreateMainThread(struct NaClApp *nap,
621 : int argc,
622 : char **argv,
623 : char const *const *envp) NACL_WUR;
624 :
625 : int NaClWaitForMainThreadToExit(struct NaClApp *nap);
626 :
627 : /*
628 : * Used by syscall code.
629 : */
630 : int32_t NaClCreateAdditionalThread(struct NaClApp *nap,
631 : uintptr_t prog_ctr,
632 : uintptr_t stack_ptr,
633 : uint32_t user_tls1,
634 : uint32_t user_tls2) NACL_WUR;
635 :
636 : void NaClLoadTrampoline(struct NaClApp *nap, enum NaClAslrMode aslr_mode);
637 :
638 : void NaClLoadSpringboard(struct NaClApp *nap);
639 :
640 : static const uintptr_t kNaClBadAddress = (uintptr_t) -1;
641 :
642 : #include "native_client/src/trusted/service_runtime/sel_ldr-inl.h"
643 :
644 : /*
645 : * Looks up a descriptor in the open-file table. An additional
646 : * reference is taken on the returned NaClDesc object (if non-NULL).
647 : * The caller is responsible for invoking NaClDescUnref() on it when
648 : * done.
649 : */
650 : struct NaClDesc *NaClAppGetDesc(struct NaClApp *nap,
651 : int d);
652 :
653 : /* NaClAppSetDesc() is defined in src/public/chrome_main.h. */
654 :
655 : int32_t NaClAppSetDescAvail(struct NaClApp *nap,
656 : struct NaClDesc *ndp);
657 :
658 : /*
659 : * Versions that are called while already holding the desc_mu lock
660 : */
661 : struct NaClDesc *NaClAppGetDescMu(struct NaClApp *nap,
662 : int d);
663 :
664 : void NaClAppSetDescMu(struct NaClApp *nap,
665 : int d,
666 : struct NaClDesc *ndp);
667 :
668 : int32_t NaClAppSetDescAvailMu(struct NaClApp *nap,
669 : struct NaClDesc *ndp);
670 :
671 :
672 : int NaClAddThread(struct NaClApp *nap,
673 : struct NaClAppThread *natp);
674 :
675 : int NaClAddThreadMu(struct NaClApp *nap,
676 : struct NaClAppThread *natp);
677 :
678 : void NaClRemoveThread(struct NaClApp *nap,
679 : int thread_num);
680 :
681 : void NaClRemoveThreadMu(struct NaClApp *nap,
682 : int thread_num);
683 :
684 : struct NaClAppThread *NaClGetThreadMu(struct NaClApp *nap,
685 : int thread_num);
686 :
687 : void NaClAppInitialDescriptorHookup(struct NaClApp *nap);
688 :
689 : void NaClCreateServiceSocket(struct NaClApp *nap);
690 :
691 : void NaClSetUpBootstrapChannel(struct NaClApp *nap,
692 : NaClHandle inherited_desc);
693 :
694 : void NaClSecureCommandChannel(struct NaClApp *nap);
695 :
696 : /*
697 : * Loads the |nexe| as a NaCl app module.
698 : * The |load_cb| callback is invoked before the the |nexe| is loaded to allow
699 : * validation being run in parallel.
700 : */
701 : void NaClAppLoadModule(struct NaClApp *self,
702 : struct NaClDesc *nexe,
703 : void (*load_cb)(void *instance_data,
704 : NaClErrorCode status),
705 : void *instance_data);
706 :
707 : int NaClAppRuntimeHostSetup(struct NaClApp *self,
708 : struct NaClRuntimeHostInterface *host_itf);
709 :
710 : int NaClAppDescQuotaSetup(struct NaClApp *self,
711 : struct NaClDescQuotaInterface *rev_quota);
712 :
713 : /*
714 : * Starts the NaCl app, the |start_cb| callback is invoked before the
715 : * application is actually started.
716 : */
717 : void NaClAppStartModule(struct NaClApp *self,
718 : void (*start_cb)(void *instance_data,
719 : NaClErrorCode status),
720 : void *instance_data);
721 :
722 : void NaClAppShutdown(struct NaClApp *self,
723 : int exit_status);
724 :
725 : NaClErrorCode NaClWaitForLoadModuleCommand(struct NaClApp *nap) NACL_WUR;
726 :
727 : NaClErrorCode NaClWaitForLoadModuleStatus(struct NaClApp *nap) NACL_WUR;
728 :
729 : NaClErrorCode NaClWaitForStartModuleCommand(struct NaClApp *nap) NACL_WUR;
730 :
731 : /*
732 : * NaClBlockIfCommandChannelExists is used during error exit. If
733 : * there is a secure command channel, we sent an RPC reply with the
734 : * reason that the nexe was rejected. If we exit immediately, that
735 : * reply may still be in-flight and the various channel closure (esp
736 : * reverse channels, if those were set up) may be detected first by
737 : * the controlling process on the other end of the command channel or
738 : * reverse channel. When channel closure wins the race against the
739 : * RPC reply, it would result in a crash being reported, rather than
740 : * the error code carried in the RPC reply. We want to ensure that
741 : * the RPC reply to get processed. Instead of allowing the service
742 : * runtime process to exit, we block the main thread and wait for the
743 : * hard-shutdown on the command channel or command channel closure.
744 : *
745 : * If there is no command channel, NaClBlockIfCommandChannelExists
746 : * just returns immediately.
747 : */
748 : void NaClBlockIfCommandChannelExists(struct NaClApp *nap);
749 :
750 : void NaClFillMemoryRegionWithHalt(void *start, size_t size);
751 :
752 : void NaClFillTrampolineRegion(struct NaClApp *nap);
753 :
754 : void NaClFillEndOfTextRegion(struct NaClApp *nap);
755 :
756 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
757 :
758 : int NaClMakePcrelThunk(struct NaClApp *nap, enum NaClAslrMode aslr_mode);
759 :
760 : #endif
761 :
762 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
763 :
764 : int NaClMakeDispatchAddrs(struct NaClApp *nap);
765 :
766 : void NaClPatchOneTrampolineCall(uintptr_t call_target_addr,
767 : uintptr_t target_addr);
768 :
769 : #endif
770 :
771 : void NaClPatchOneTrampoline(struct NaClApp *nap,
772 : uintptr_t target_addr);
773 : /*
774 : * target is an absolute address in the source region. the patch code
775 : * will figure out the corresponding address in the destination region
776 : * and modify as appropriate. this makes it easier to specify, since
777 : * the target is typically the address of some symbol from the source
778 : * template.
779 : */
780 : struct NaClPatch {
781 : uintptr_t target;
782 : uint64_t value;
783 : };
784 :
785 : struct NaClPatchInfo {
786 : uintptr_t dst;
787 : uintptr_t src;
788 : size_t nbytes;
789 :
790 : struct NaClPatch *abs16;
791 : size_t num_abs16;
792 :
793 : struct NaClPatch *abs32;
794 : size_t num_abs32;
795 :
796 : struct NaClPatch *abs64;
797 : size_t num_abs64;
798 :
799 : #if NACL_TARGET_SUBARCH == 32
800 : uintptr_t *rel32;
801 : size_t num_rel32;
802 : #endif
803 :
804 : uintptr_t *rel64;
805 : size_t num_rel64;
806 : };
807 :
808 : struct NaClPatchInfo *NaClPatchInfoCtor(struct NaClPatchInfo *self);
809 :
810 : void NaClApplyPatchToMemory(struct NaClPatchInfo *patch);
811 :
812 : int NaClAppThreadInitArchSpecific(struct NaClAppThread *natp,
813 : nacl_reg_t prog_ctr,
814 : nacl_reg_t stack_ptr);
815 :
816 : void NaClVmHoleWaitToStartThread(struct NaClApp *nap);
817 :
818 : void NaClVmHoleThreadStackIsSafe(struct NaClApp *nap);
819 :
820 : void NaClVmHoleOpeningMu(struct NaClApp *nap);
821 :
822 : void NaClVmHoleClosingMu(struct NaClApp *nap);
823 :
824 : /*
825 : * More VM race detection. In Windows, when we unmap or mmap over
826 : * existing memory, we cannot maintain the address space reservation
827 : * -- we have to unmap the original mapping with the appropriate
828 : * unmapping function (VirtualFree or UnmapViewOfFile) before we can
829 : * VirtualAlloc to reserve the addresss pace, leaving a timing window
830 : * where another thread (possibly injected into the binary, e.g.,
831 : * antivirus code) might map something else into. We stop user-space
832 : * threads when mmap/munmap occurs and detect if the temporary VM hole
833 : * was filled by some other thread (and abort the process in that
834 : * case), so that untrusted code cannot observe nor modify the memory
835 : * that lands in the hole. However, we still have the case where the
836 : * untrusted code's threads aren't running user-space code -- a thread
837 : * may have entered into a syscall handler. We don't stop such
838 : * threads, because they might be holding locks that the memory
839 : * mapping functions need. This means that, for example, a malicious
840 : * application could -- assuming it could create the innocent thread
841 : * race condition -- have one thread invoke the "write" NaCl syscall,
842 : * enter into the host OS "write" syscall code in the NaCl syscall
843 : * handler, then have another thread mmap (or munmap) the memory where
844 : * the source memory region from which the content to be written
845 : * resides, and as a side effect of this race, exfiltrate memory
846 : * contents that NaCl modules aren't supposed to be able to access.
847 : *
848 : * NB: we do not try to prevent data races such as two "read" syscalls
849 : * simultaneously trying to write the same memory region, or
850 : * concurrent "read" and "write" syscalls racing on the same memory
851 : * region..
852 : */
853 :
854 : /*
855 : * Some potentially blocking I/O operation is about to start. Syscall
856 : * handlers implement DMA-style access where the host-OS syscalls
857 : * directly read/write untrusted memory, so we must record the
858 : * affected memory ranges as "in use" by I/O operations.
859 : */
860 : void NaClVmIoWillStart(struct NaClApp *nap,
861 : uint32_t addr_first_usr,
862 : uint32_t addr_last_usr);
863 :
864 :
865 : /*
866 : * It is a fatal error to have an invocation of NaClVmIoHasEnded whose
867 : * arguments do not match those of an earlier, unmatched invocation of
868 : * NaClVmIoWillStart.
869 : */
870 : void NaClVmIoHasEnded(struct NaClApp *nap,
871 : uint32_t addr_first_usr,
872 : uint32_t addr_last_usr);
873 :
874 : /*
875 : * Used by operations (mmap, munmap) that will open a VM hole.
876 : * Invoked while holding the VM lock. Check that no I/O is pending;
877 : * abort the app if the app is racing I/O operations against VM
878 : * operations.
879 : */
880 : void NaClVmIoPendingCheck_mu(struct NaClApp *nap,
881 : uint32_t addr_first_usr,
882 : uint32_t addr_last_usr);
883 :
884 : void NaClGdbHook(struct NaClApp const *nap);
885 :
886 : #if NACL_LINUX
887 : void NaClHandleBootstrapArgs(int *argc_p, char ***argv_p);
888 : void NaClHandleRDebug(const char *switch_value, char *argv0);
889 : void NaClHandleReservedAtZero(const char *switch_value);
890 : #else
891 1 : static INLINE void NaClHandleBootstrapArgs(int *argc_p, char ***argv_p) {
892 2 : UNREFERENCED_PARAMETER(argc_p);
893 2 : UNREFERENCED_PARAMETER(argv_p);
894 1 : }
895 : #endif
896 :
897 : EXTERN_C_END
898 :
899 : #endif /* NATIVE_CLIENT_SRC_TRUSTED_SERVICE_RUNTIME_SEL_LDR_H_ */
|