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.
8 * NaCl Simple/secure ELF loader (NaCl SEL).
10 * This loader can only process NaCl object files as produced using
11 * the NaCl toolchain. Other ELF files will be rejected.
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
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.
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.
28 #ifndef NATIVE_CLIENT_SRC_TRUSTED_SERVICE_RUNTIME_SEL_LDR_H_
29 #define NATIVE_CLIENT_SRC_TRUSTED_SERVICE_RUNTIME_SEL_LDR_H_ 1
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"
36 #include "native_client/src/public/nacl_app.h"
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"
42 #include "native_client/src/shared/srpc/nacl_srpc.h"
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"
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"
59 #include "native_client/src/trusted/validator/ncvalidate.h"
63 #define NACL_SERVICE_PORT_DESCRIPTOR 3
64 #define NACL_SERVICE_ADDRESS_DESCRIPTOR 4
66 #define NACL_DEFAULT_STACK_MAX (16 << 20) /* main thread stack */
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;
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);
84 enum NaClResourcePhase {
85 NACL_RESOURCE_PHASE_START,
86 NACL_RESOURCE_PHASE_RUNTIME_HOST
90 enum NaClDebugExceptionHandlerState {
91 NACL_DEBUG_EXCEPTION_HANDLER_NOT_STARTED,
92 NACL_DEBUG_EXCEPTION_HANDLER_STARTED,
93 NACL_DEBUG_EXCEPTION_HANDLER_FAILED
96 * Callback function used to request that an exception handler be
97 * attached using the Windows debug API. See sel_main_chrome.h.
99 typedef int (*NaClAttachDebugExceptionHandlerFunc)(const void *info,
103 struct NaClSpringboardInfo {
104 /* These are addresses in untrusted address space (relative to mem_start). */
111 * public, user settable prior to app start.
114 uintptr_t stack_size;
115 uint32_t initial_nexe_max_code_bytes;
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
125 * Determined at load time; OS-determined.
126 * Read-only after load, so accesses do not require locking.
130 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
131 uintptr_t pcrel_thunk;
132 uintptr_t pcrel_thunk_end;
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;
140 /* only used for ET_EXEC: for CS restriction */
141 uintptr_t static_text_end;
143 * relative to mem_start; ro after app starts. memsz from phdr
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
151 uintptr_t dynamic_text_start;
152 uintptr_t dynamic_text_end;
155 * rodata_start and data_start may be 0 if these segments are not
156 * present in the executable.
158 uintptr_t rodata_start; /* initialized data, ro */
159 uintptr_t data_start; /* initialized data/bss, rw */
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.
171 /* see break_addr below */
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.
180 uintptr_t initial_entry_pt;
181 uintptr_t user_entry_pt;
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.
189 /* common to both ELF executables and relocatable load images */
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;
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.
202 struct NaClDesc *service_port;
203 struct NaClDesc *service_address;
205 struct NaClDesc *secure_service_port;
206 struct NaClDesc *secure_service_address;
208 struct NaClDesc *bootstrap_channel;
211 * The main NaCl executable may already be validated during ELF
212 * loading, where after a validation cache hit the code gets mmapped
213 * into memory if the file descriptor is "blessed" as referring to a
214 * file which the embedding environment guarantees to be effectively
215 * immutable. If it did not validate or the file descriptor is not
216 * blessed, then the code is read into memory, and we will validate
217 * it later in the code path, in NaClAppLoadFileAslr.
219 int main_exe_prevalidated; /* bool */
222 struct NaClCondVar cv;
226 * invariant: !(vm_hole_may_exist && threads_launching != 0).
227 * vm_hole_may_exist is set while mmap/munmap manipulates the memory
228 * map, and threads_launching is set while a thread is launching
229 * (and a trusted thread stack is being allocated).
231 * strictly speaking, vm_hole_may_exist need not be present, since
232 * the vm code ensures that 0 == threads_launching and then holds
233 * the lock for the duration of the VM operation. it is safer this
234 * way, in case we later introduce code that might want to
235 * temporarily drop the process lock.
237 int vm_hole_may_exist;
238 int threads_launching;
242 * An array of NaCl syscall handlers. The length of the array must be
243 * at least NACL_MAX_SYSCALLS.
245 struct NaClSyscallTableEntry *syscall_table;
248 * Name service must launch after mu, cv, vm_hole_may_exit,
249 * threads_launching are initialized.
251 struct NaClNameService *name_service; /* default name server */
252 struct NaClDesc *name_service_conn_cap;
254 struct NaClSecureService *secure_service;
256 struct NaClKernelService *kernel_service;
258 struct NaClResourceNaClApp resources;
259 enum NaClResourcePhase resource_phase;
261 struct NaClRuntimeHostInterface *runtime_host_interface;
262 struct NaClDescQuotaInterface *desc_quota_interface;
265 * The ordering in this enum is important. We use the ordering
266 * to check that the status of module initialization; the state
267 * is really being used as a state machine. Please do not change
268 * the ordering, if you need to add a new state please do so at
269 * the appropriate position dependending on a module loading phase.
272 enum NaClModuleInitializationState {
273 NACL_MODULE_UNINITIALIZED = 0,
276 NACL_MODULE_STARTING,
279 } module_initialization_state;
280 NaClErrorCode module_load_status;
283 * runtime info below, thread state, etc; initialized only when app
284 * is run. Mutex mu protects access to mem_map and other member
285 * variables while the application is running and may be
286 * multithreaded; thread, desc members have their own locks. At
287 * other times it is assumed that only one thread is
288 * constructing/loading the NaClApp and that no mutual exclusion is
293 * memory map is in user addresses.
295 struct NaClVmmap mem_map;
297 struct NaClIntervalMultiset *mem_io_regions;
300 * This is the effector interface object that is used to manipulate
301 * NaCl apps by the objects in the NaClDesc class hierarchy. This
302 * is used by this NaClApp when making NaClDesc method calls from
303 * syscall handlers. Currently, this is when NaClDesc objects need
304 * to manipulate the untrusted address space -- the mmap
305 * implementation need to unmap the untrusted pages, and on Windows
306 * this requires different calls depending on how the pages were
309 struct NaClDescEffector *effp;
312 * may reject nexes that are incompatible w/ dynamic-text in the near future
314 int enable_dyncode_syscalls;
315 int use_shm_for_dynamic_text;
316 struct NaClDesc *text_shm;
317 struct NaClMutex dynamic_load_mutex;
319 * This records which pages in text_shm have been allocated. When a
320 * page is allocated, it is filled with halt instructions and then
321 * made executable by untrusted code.
323 uint8_t *dynamic_page_bitmap;
326 * The array of dynamic_regions is maintained in sorted order
327 * Accesses must be protected by dynamic_load_mutex.
329 struct NaClDynamicRegion *dynamic_regions;
330 int num_dynamic_regions;
331 int dynamic_regions_allocated;
334 * These variables are used for caching mapped writable views of the
335 * dynamic text segment. See CachedMapWritableText in nacl_text.c.
336 * Accesses must be protected by dynamic_load_mutex
338 uint32_t dynamic_mapcache_offset;
339 uint32_t dynamic_mapcache_size;
340 uintptr_t dynamic_mapcache_ret;
343 * Monotonically increasing generation number used for deletion
344 * Accesses must be protected by dynamic_load_mutex
346 int dynamic_delete_generation;
352 NaClCPUFeatures *cpu_features;
353 int fixed_feature_cpu_mode;
354 struct NaClValidationCache *validation_cache;
355 int ignore_validator_result;
357 int validator_stub_out_mode;
359 int enable_list_mappings;
360 /* Whether or not the app is a PNaCl app. Boolean. */
363 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
364 uint16_t code_seg_sel;
365 uint16_t data_seg_sel;
368 uintptr_t break_addr; /* user addr */
369 /* data_end <= break_addr is an invariant */
372 * Thread table lock threads_mu is higher in the locking order than
373 * the thread locks, i.e., threads_mu must be acqured w/o holding
374 * any per-thread lock (natp->mu).
376 struct NaClMutex threads_mu;
377 struct DynArray threads; /* NaClAppThread pointers */
378 int num_threads; /* number actually running */
380 struct NaClFastMutex desc_mu;
381 struct DynArray desc_tbl; /* NaClDesc pointers */
383 const struct NaClDebugCallbacks *debug_stub_callbacks;
385 uint16_t debug_stub_port;
387 struct NaClDesc *main_nexe_desc;
388 struct NaClDesc *irt_nexe_desc;
390 struct NaClMutex exception_mu;
391 uint32_t exception_handler;
392 int enable_exception_handling;
394 enum NaClDebugExceptionHandlerState debug_exception_handler_state;
395 NaClAttachDebugExceptionHandlerFunc attach_debug_exception_handler_func;
398 * enable_faulted_thread_queue is a boolean which enables handling
399 * of untrusted faults which is used by the debug stub. When an
400 * untrusted thread faults, it is blocked until
401 * NaClAppThreadUnblockIfFaulted() is called on the thread.
403 int enable_faulted_thread_queue;
405 * faulted_thread_count is the number of NaClAppThreads for which
406 * fault_signal is non-zero.
408 Atomic32 faulted_thread_count;
411 * An event that is signaled by debug exception handler process when it fills
412 * fault_signal field with non-zero value for some NaClAppThread.
414 HANDLE faulted_thread_event;
417 * A file descriptor of a pipe which becomes available for reading in
418 * the event that fault_signal for some NaClAppThread becomes non-zero.
420 int faulted_thread_fd_read;
421 int faulted_thread_fd_write;
425 * Cache of sysconf(_SC_NPROCESSORS_ONLN) (or equivalent) result.
427 int sc_nprocessors_onln;
429 const struct NaClValidatorInterface *validator;
432 * Mutex for protecting futex_wait_list_head. Lock ordering:
433 * NaClApp::mu may be claimed after futex_wait_list_mu but never
436 struct NaClMutex futex_wait_list_mu;
438 * This is the sentinel node for a doubly linked list of
439 * NaClAppThreads. This lists the threads that are waiting to be
440 * woken up by futex_wake(). This list must only be accessed while
441 * holding the mutex futex_wait_list_mu.
443 struct NaClListNode futex_wait_list_head;
448 void NaClAppIncrVerbosity(void);
451 * Initializes a NaCl application with the default parameters
452 * and the specified syscall table.
454 * If invoked after the outer sandbox is enabled, the caller is
455 * responsible for initializing the sc_nprocessors_onln member to a
458 * nap is a pointer to the NaCl object that is being filled in.
460 * table is the NaCl syscall table. The syscall table must contain at least
461 * NACL_MAX_SYSCALLS valid entries.
463 * Caution! Syscall handlers must be extremely careful with respect to
464 * argument validation, including time-of-check vs time-of-use defense, etc.
466 int NaClAppWithSyscallTableCtor(struct NaClApp *nap,
467 struct NaClSyscallTableEntry *table) NACL_WUR;
469 * Standard Ctor for NaClApp objects. Installs default syscall
472 * If invoked after the outer sandbox is enabled, the caller is
473 * responsible for initializing the sc_nprocessors_onln member to a
476 * nap is a pointer to the NaCl object that is being filled in.
478 int NaClAppCtor(struct NaClApp *nap) NACL_WUR;
481 * Loads a NaCl ELF file into memory in preparation for running it.
483 * gp is a pointer to a generic I/O object and should be a GioMem with
484 * a memory buffer containing the file read entirely into memory if
485 * the file system might be subject to race conditions (e.g., another
486 * thread / process might modify a downloaded NaCl ELF file while we
487 * are loading it here).
489 * nap is a pointer to the NaCl object that is being filled in. it
490 * should be properly constructed via NaClAppCtor.
492 * return value: one of the LOAD_* values defined in
493 * nacl_error_code.h. TODO: add some error detail string and hang
494 * that off the nap object, so that more details are available w/o
495 * incrementing verbosity (and polluting stdout).
497 * note: it may be necessary to flush the icache if the memory
498 * allocated for use had already made it into the icache from another
499 * NaCl application instance, and the icache does not detect
500 * self-modifying code / data writes and automatically invalidate the
503 NaClErrorCode NaClAppLoadFile(struct NaClDesc *ndp,
504 struct NaClApp *nap) NACL_WUR;
507 * Just like NaClAppLoadFile, but allow control over ASLR.
509 NaClErrorCode NaClAppLoadFileAslr(struct NaClDesc *ndp,
511 enum NaClAslrMode aslr_mode) NACL_WUR;
514 NaClErrorCode NaClAppLoadFileDynamically(
516 struct NaClDesc *ndp,
517 struct NaClValidationMetadata *metadata) NACL_WUR;
519 void NaClAppPrintDetails(struct NaClApp *nap,
522 NaClErrorCode NaClLoadImage(struct Gio *gp,
523 struct NaClApp *nap) NACL_WUR;
525 int NaClValidateCode(struct NaClApp *nap,
526 uintptr_t guest_addr,
529 const struct NaClValidationMetadata *metadata) NACL_WUR;
532 * Validates that the code found at data_old can safely be replaced with
533 * the code found at data_new.
535 int NaClValidateCodeReplacement(struct NaClApp *nap,
536 uintptr_t guest_addr,
542 * Copies code from data_new to data_old in a thread-safe way.
544 int NaClCopyCode(struct NaClApp *nap, uintptr_t guest_addr,
545 uint8_t *data_old, uint8_t *data_new,
549 * Copies an instruction in a thread-safe way. Used by validators.
551 int NaClCopyInstruction(uint8_t *dst, uint8_t *src, uint8_t sz);
553 NaClErrorCode NaClValidateImage(struct NaClApp *nap) NACL_WUR;
556 int NaClAddrIsValidEntryPt(struct NaClApp *nap,
560 * Takes ownership of descriptor, i.e., when NaCl app closes, it's gone.
562 void NaClAddHostDescriptor(struct NaClApp *nap,
568 * Takes ownership of handle.
570 void NaClAddImcHandle(struct NaClApp *nap,
575 * Launch system-level service threads. After this, access to the
576 * NaClApp object must be done in a thread-safe manner, using nap->mu
577 * etc, or access only read-only data.
579 * NB: the "secure command channel" thread should have already started
580 * (if enabled); that thread must take care to not race with the main
581 * thread that is continuing to set up the NaCl module as well.
583 int NaClAppLaunchServiceThreads(struct NaClApp *nap);
586 * Report the low eight bits of |exit_status| via the reverse channel
587 * in |nap|, if one exists, to whomever is interested. This usually
588 * involves an RPC. Returns true if successfully reported.
590 * Also mark nap's exit_status and running member variables, announce
591 * via condvar that the nexe should be considered no longer running.
593 * Returns true (non-zero) if exit status was reported via the reverse
594 * channel, and false (0) otherwise.
596 int NaClReportExitStatus(struct NaClApp *nap, int exit_status);
599 * Get the top of the initial thread's stack. Returns a user address.
601 uintptr_t NaClGetInitialStackTop(struct NaClApp *nap);
604 * Used to launch the main thread. NB: calling thread may in the
605 * future become the main NaCl app thread, and this function will
606 * return only after the NaCl app main thread exits. In such an
607 * alternative design, NaClWaitForMainThreadToExit will become a
610 int NaClCreateMainThread(struct NaClApp *nap,
613 char const *const *envp) NACL_WUR;
615 int NaClWaitForMainThreadToExit(struct NaClApp *nap);
618 * Used by syscall code.
620 int32_t NaClCreateAdditionalThread(struct NaClApp *nap,
624 uint32_t user_tls2) NACL_WUR;
626 void NaClLoadTrampoline(struct NaClApp *nap, enum NaClAslrMode aslr_mode);
628 void NaClLoadSpringboard(struct NaClApp *nap);
630 static const uintptr_t kNaClBadAddress = (uintptr_t) -1;
632 #include "native_client/src/trusted/service_runtime/sel_ldr-inl.h"
635 * Looks up a descriptor in the open-file table. An additional
636 * reference is taken on the returned NaClDesc object (if non-NULL).
637 * The caller is responsible for invoking NaClDescUnref() on it when
640 struct NaClDesc *NaClAppGetDesc(struct NaClApp *nap,
643 /* NaClAppSetDesc() is defined in src/public/chrome_main.h. */
645 int32_t NaClAppSetDescAvail(struct NaClApp *nap,
646 struct NaClDesc *ndp);
649 * Versions that are called while already holding the desc_mu lock
651 struct NaClDesc *NaClAppGetDescMu(struct NaClApp *nap,
654 void NaClAppSetDescMu(struct NaClApp *nap,
656 struct NaClDesc *ndp);
658 int32_t NaClAppSetDescAvailMu(struct NaClApp *nap,
659 struct NaClDesc *ndp);
662 int NaClAddThread(struct NaClApp *nap,
663 struct NaClAppThread *natp);
665 int NaClAddThreadMu(struct NaClApp *nap,
666 struct NaClAppThread *natp);
668 void NaClRemoveThread(struct NaClApp *nap,
671 void NaClRemoveThreadMu(struct NaClApp *nap,
674 struct NaClAppThread *NaClGetThreadMu(struct NaClApp *nap,
677 void NaClAppInitialDescriptorHookup(struct NaClApp *nap);
679 void NaClCreateServiceSocket(struct NaClApp *nap);
681 void NaClSetUpBootstrapChannel(struct NaClApp *nap,
682 NaClHandle inherited_desc);
684 void NaClSecureCommandChannel(struct NaClApp *nap);
687 * Loads the |nexe| as a NaCl app module.
688 * The |load_cb| callback is invoked before the the |nexe| is loaded to allow
689 * validation being run in parallel.
691 void NaClAppLoadModule(struct NaClApp *self,
692 struct NaClDesc *nexe,
693 void (*load_cb)(void *instance_data,
694 NaClErrorCode status),
695 void *instance_data);
697 int NaClAppRuntimeHostSetup(struct NaClApp *self,
698 struct NaClRuntimeHostInterface *host_itf);
700 int NaClAppDescQuotaSetup(struct NaClApp *self,
701 struct NaClDescQuotaInterface *rev_quota);
704 * Starts the NaCl app, the |start_cb| callback is invoked before the
705 * application is actually started.
707 void NaClAppStartModule(struct NaClApp *self,
708 void (*start_cb)(void *instance_data,
709 NaClErrorCode status),
710 void *instance_data);
712 void NaClAppShutdown(struct NaClApp *self,
715 NaClErrorCode NaClWaitForLoadModuleCommand(struct NaClApp *nap) NACL_WUR;
717 NaClErrorCode NaClWaitForLoadModuleStatus(struct NaClApp *nap) NACL_WUR;
719 NaClErrorCode NaClWaitForStartModuleCommand(struct NaClApp *nap) NACL_WUR;
722 * NaClBlockIfCommandChannelExists is used during error exit. If
723 * there is a secure command channel, we sent an RPC reply with the
724 * reason that the nexe was rejected. If we exit immediately, that
725 * reply may still be in-flight and the various channel closure (esp
726 * reverse channels, if those were set up) may be detected first by
727 * the controlling process on the other end of the command channel or
728 * reverse channel. When channel closure wins the race against the
729 * RPC reply, it would result in a crash being reported, rather than
730 * the error code carried in the RPC reply. We want to ensure that
731 * the RPC reply to get processed. Instead of allowing the service
732 * runtime process to exit, we block the main thread and wait for the
733 * hard-shutdown on the command channel or command channel closure.
735 * If there is no command channel, NaClBlockIfCommandChannelExists
736 * just returns immediately.
738 void NaClBlockIfCommandChannelExists(struct NaClApp *nap);
740 void NaClFillMemoryRegionWithHalt(void *start, size_t size);
742 void NaClFillTrampolineRegion(struct NaClApp *nap);
744 void NaClFillEndOfTextRegion(struct NaClApp *nap);
746 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
748 int NaClMakePcrelThunk(struct NaClApp *nap, enum NaClAslrMode aslr_mode);
752 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
754 int NaClMakeDispatchAddrs(struct NaClApp *nap);
756 void NaClPatchOneTrampolineCall(uintptr_t call_target_addr,
757 uintptr_t target_addr);
761 void NaClPatchOneTrampoline(struct NaClApp *nap,
762 uintptr_t target_addr);
764 * target is an absolute address in the source region. the patch code
765 * will figure out the corresponding address in the destination region
766 * and modify as appropriate. this makes it easier to specify, since
767 * the target is typically the address of some symbol from the source
775 struct NaClPatchInfo {
780 struct NaClPatch *abs16;
783 struct NaClPatch *abs32;
786 struct NaClPatch *abs64;
789 #if NACL_TARGET_SUBARCH == 32
798 struct NaClPatchInfo *NaClPatchInfoCtor(struct NaClPatchInfo *self);
800 void NaClApplyPatchToMemory(struct NaClPatchInfo *patch);
802 int NaClAppThreadInitArchSpecific(struct NaClAppThread *natp,
804 nacl_reg_t stack_ptr);
806 void NaClVmHoleWaitToStartThread(struct NaClApp *nap);
808 void NaClVmHoleThreadStackIsSafe(struct NaClApp *nap);
810 void NaClVmHoleOpeningMu(struct NaClApp *nap);
812 void NaClVmHoleClosingMu(struct NaClApp *nap);
815 * More VM race detection. In Windows, when we unmap or mmap over
816 * existing memory, we cannot maintain the address space reservation
817 * -- we have to unmap the original mapping with the appropriate
818 * unmapping function (VirtualFree or UnmapViewOfFile) before we can
819 * VirtualAlloc to reserve the addresss pace, leaving a timing window
820 * where another thread (possibly injected into the binary, e.g.,
821 * antivirus code) might map something else into. We stop user-space
822 * threads when mmap/munmap occurs and detect if the temporary VM hole
823 * was filled by some other thread (and abort the process in that
824 * case), so that untrusted code cannot observe nor modify the memory
825 * that lands in the hole. However, we still have the case where the
826 * untrusted code's threads aren't running user-space code -- a thread
827 * may have entered into a syscall handler. We don't stop such
828 * threads, because they might be holding locks that the memory
829 * mapping functions need. This means that, for example, a malicious
830 * application could -- assuming it could create the innocent thread
831 * race condition -- have one thread invoke the "write" NaCl syscall,
832 * enter into the host OS "write" syscall code in the NaCl syscall
833 * handler, then have another thread mmap (or munmap) the memory where
834 * the source memory region from which the content to be written
835 * resides, and as a side effect of this race, exfiltrate memory
836 * contents that NaCl modules aren't supposed to be able to access.
838 * NB: we do not try to prevent data races such as two "read" syscalls
839 * simultaneously trying to write the same memory region, or
840 * concurrent "read" and "write" syscalls racing on the same memory
845 * Some potentially blocking I/O operation is about to start. Syscall
846 * handlers implement DMA-style access where the host-OS syscalls
847 * directly read/write untrusted memory, so we must record the
848 * affected memory ranges as "in use" by I/O operations.
850 void NaClVmIoWillStart(struct NaClApp *nap,
851 uint32_t addr_first_usr,
852 uint32_t addr_last_usr);
856 * It is a fatal error to have an invocation of NaClVmIoHasEnded whose
857 * arguments do not match those of an earlier, unmatched invocation of
860 void NaClVmIoHasEnded(struct NaClApp *nap,
861 uint32_t addr_first_usr,
862 uint32_t addr_last_usr);
865 * Used by operations (mmap, munmap) that will open a VM hole.
866 * Invoked while holding the VM lock. Check that no I/O is pending;
867 * abort the app if the app is racing I/O operations against VM
870 void NaClVmIoPendingCheck_mu(struct NaClApp *nap,
871 uint32_t addr_first_usr,
872 uint32_t addr_last_usr);
874 void NaClGdbHook(struct NaClApp const *nap);
877 void NaClHandleBootstrapArgs(int *argc_p, char ***argv_p);
878 void NaClHandleRDebug(const char *switch_value, char *argv0);
879 void NaClHandleReservedAtZero(const char *switch_value);
881 static INLINE void NaClHandleBootstrapArgs(int *argc_p, char ***argv_p) {
882 UNREFERENCED_PARAMETER(argc_p);
883 UNREFERENCED_PARAMETER(argv_p);
889 #endif /* NATIVE_CLIENT_SRC_TRUSTED_SERVICE_RUNTIME_SEL_LDR_H_ */