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/nacl_base.h"
32 : #include "native_client/src/include/portability.h"
33 : #include "native_client/src/include/elf.h"
34 :
35 : #include "native_client/src/shared/platform/nacl_host_desc.h"
36 : #include "native_client/src/shared/platform/nacl_log.h"
37 : #include "native_client/src/shared/platform/nacl_threads.h"
38 :
39 : #include "native_client/src/shared/srpc/nacl_srpc.h"
40 :
41 : #include "native_client/src/trusted/service_runtime/dyn_array.h"
42 : #include "native_client/src/trusted/service_runtime/nacl_config_dangerous.h"
43 : #include "native_client/src/trusted/service_runtime/nacl_error_code.h"
44 : #include "native_client/src/trusted/service_runtime/nacl_kern_services.h"
45 : #include "native_client/src/trusted/service_runtime/nacl_resource.h"
46 :
47 : #include "native_client/src/trusted/service_runtime/sel_mem.h"
48 : #include "native_client/src/trusted/service_runtime/sel_util.h"
49 : #include "native_client/src/trusted/service_runtime/sel_rt.h"
50 :
51 : #include "native_client/src/trusted/service_runtime/name_service/name_service.h"
52 :
53 : #include "native_client/src/trusted/validator/cpufeatures.h"
54 :
55 : EXTERN_C_BEGIN
56 :
57 : #define NACL_SERVICE_PORT_DESCRIPTOR 3
58 : #define NACL_SERVICE_ADDRESS_DESCRIPTOR 4
59 :
60 : #define NACL_DEFAULT_STACK_MAX (16 << 20) /* main thread stack */
61 :
62 : #define NACL_SANDBOX_CHROOT_FD "SBX_D"
63 :
64 : struct NaClAppThread;
65 : struct NaClDesc; /* see native_client/src/trusted/desc/nacl_desc_base.h */
66 : struct NaClDynamicRegion;
67 : struct NaClManifestProxy;
68 : struct NaClReverseQuotaInterface;
69 : struct NaClSecureService;
70 : struct NaClSecureReverseService;
71 : struct NaClThreadInterface; /* see sel_ldr_thread_interface.h */
72 :
73 : struct NaClDebugCallbacks {
74 : void (*thread_create_hook)(struct NaClAppThread *natp);
75 : void (*thread_exit_hook)(struct NaClAppThread *natp);
76 : void (*process_exit_hook)(int exit_status);
77 : };
78 :
79 : enum NaClResourcePhase {
80 : NACL_RESOURCE_PHASE_START,
81 : NACL_RESOURCE_PHASE_REV_CHAN
82 : };
83 :
84 : struct NaClApp {
85 : /*
86 : * public, user settable prior to app start.
87 : */
88 : uint8_t addr_bits;
89 : uintptr_t stack_size;
90 : /*
91 : * stack_size is the maximum size of the (main) stack. The stack
92 : * memory is eager allocated (mapped in w/o MAP_NORESERVE) so
93 : * there must be enough swap space; page table entries are not
94 : * populated (no MAP_POPULATE), so actual accesses will likely
95 : * incur page faults.
96 : */
97 :
98 : /*
99 : * aux_info can contain an arbitrary NUL terminated string. It is
100 : * set via the load_module RPC, and is intended to enable the
101 : * browser plugin to provide information that would be useful for
102 : * the debugger.
103 : */
104 : char *aux_info;
105 :
106 : /*
107 : * Determined at load time; OS-determined.
108 : * Read-only after load, so accesses do not require locking.
109 : */
110 : uintptr_t mem_start;
111 :
112 : #if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 \
113 : && NACL_BUILD_SUBARCH == 32 && __PIC__)
114 : uintptr_t pcrel_thunk;
115 : #endif
116 : #if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 \
117 : && NACL_BUILD_SUBARCH == 64)
118 : uintptr_t dispatch_thunk;
119 : uintptr_t get_tls_fast_path;
120 : #endif
121 :
122 : /* only used for ET_EXEC: for CS restriction */
123 : uintptr_t static_text_end; /* relative to mem_start */
124 : /* ro after app starts. memsz from phdr */
125 :
126 : /*
127 : * The dynamic code area follows the static code area. These fields
128 : * are both set to static_text_end if the dynamic code area has zero
129 : * size.
130 : */
131 : uintptr_t dynamic_text_start;
132 : uintptr_t dynamic_text_end;
133 :
134 : /*
135 : * rodata_start and data_start may be 0 if these segments are not
136 : * present in the executable.
137 : */
138 : uintptr_t rodata_start; /* initialized data, ro */
139 : uintptr_t data_start; /* initialized data/bss, rw */
140 : /*
141 : * Various region sizes must be a multiple of NACL_MAP_PAGESIZE
142 : * before the NaCl app can run. The sizes from the ELF file
143 : * (p_filesz field) might not be -- that would waste space for
144 : * padding -- and while we could use p_memsz to specify padding, but
145 : * we will record the virtual addresses of the start of the segments
146 : * and figure out the gap between the p_vaddr + p_filesz of one
147 : * segment and p_vaddr of the next to determine padding.
148 : */
149 :
150 : uintptr_t data_end;
151 : /* see break_addr below */
152 :
153 : /*
154 : * initial_entry_pt is the first address in untrusted code to jump
155 : * to. When using the IRT (integrated runtime), this is provided by
156 : * the IRT library, and user_entry_pt is the entry point in the user
157 : * executable. Otherwise, initial_entry_pt is in the user
158 : * executable and user_entry_pt is zero.
159 : */
160 : uintptr_t initial_entry_pt;
161 : uintptr_t user_entry_pt;
162 :
163 : /*
164 : * bundle_size is the bundle alignment boundary for validation (16
165 : * or 32), so int is okay. This value must be a power of 2.
166 : */
167 : int bundle_size;
168 :
169 : /* common to both ELF executables and relocatable load images */
170 :
171 : uintptr_t springboard_addr; /* relative to mem_start */
172 : /*
173 : * springboard code addr for context switching into app sandbox, relative
174 : * to code sandbox CS
175 : */
176 :
177 : /*
178 : * The socket at which the app should be accepting connections. The
179 : * corresponding socket address are made available by the JavaScript
180 : * bridge to other NaCl modules.
181 : */
182 : struct NaClDesc *service_port;
183 : struct NaClDesc *service_address;
184 :
185 : struct NaClMutex mu;
186 : struct NaClCondVar cv;
187 :
188 : /*
189 : * invariant: !(vm_hole_may_exist && threads_launching != 0).
190 : * vm_hole_may_exist is set while mmap/munmap manipulates the memory
191 : * map, and threads_launching is set while a thread is launching
192 : * (and a trusted thread stack is being allocated).
193 : *
194 : * strictly speaking, vm_hole_may_exist need not be present, since
195 : * the vm code ensures that 0 == threads_launching and then holds
196 : * the lock for the duration of the VM operation. it is safer this
197 : * way, in case we later introduce code that might want to
198 : * temporarily drop the process lock.
199 : */
200 : int vm_hole_may_exist;
201 : int threads_launching;
202 :
203 : /*
204 : * An array of NaCl syscall handlers. The length of the array must be
205 : * at least NACL_MAX_SYSCALLS.
206 : */
207 : struct NaClSyscallTableEntry *syscall_table;
208 :
209 : /*
210 : * Name service must launch after mu, cv, vm_hole_may_exit,
211 : * threads_launching are initialized.
212 : */
213 : struct NaClNameService *name_service; /* default name server */
214 : struct NaClDesc *name_service_conn_cap;
215 :
216 : struct NaClSecureService *secure_service;
217 : struct NaClManifestProxy *manifest_proxy;
218 : struct NaClKernService *kern_service;
219 :
220 : struct NaClResourceNaClApp resources;
221 : enum NaClResourcePhase resource_phase;
222 :
223 : struct NaClSecureReverseClient *reverse_client;
224 : enum NaClReverseChannelInitializationState {
225 : NACL_REVERSE_CHANNEL_UNINITIALIZED,
226 : NACL_REVERSE_CHANNEL_INITIALIZATION_STARTED,
227 : NACL_REVERSE_CHANNEL_INITIALIZED
228 : } reverse_channel_initialization_state;
229 : struct NaClSrpcChannel reverse_channel;
230 : struct NaClReverseQuotaInterface *reverse_quota_interface;
231 :
232 :
233 : NaClErrorCode module_load_status;
234 : int module_may_start;
235 :
236 : /*
237 : * runtime info below, thread state, etc; initialized only when app
238 : * is run. Mutex mu protects access to mem_map and other member
239 : * variables while the application is running and may be
240 : * multithreaded; thread, desc members have their own locks. At
241 : * other times it is assumed that only one thread is
242 : * constructing/loading the NaClApp and that no mutual exclusion is
243 : * needed.
244 : */
245 :
246 : /*
247 : * memory map is in user addresses.
248 : */
249 : struct NaClVmmap mem_map;
250 :
251 : /*
252 : * This is the effector interface object that is used to manipulate
253 : * NaCl apps by the objects in the NaClDesc class hierarchy. This
254 : * is used by this NaClApp when making NaClDesc method calls from
255 : * syscall handlers.
256 : */
257 : struct NaClDescEffector *effp;
258 :
259 : /*
260 : * may reject nexes that are incompatible w/ dynamic-text in the near future
261 : */
262 : int use_shm_for_dynamic_text;
263 : struct NaClDesc *text_shm;
264 : struct NaClMutex dynamic_load_mutex;
265 : /*
266 : * This records which pages in text_shm have been allocated. When a
267 : * page is allocated, it is filled with halt instructions and then
268 : * made executable by untrusted code.
269 : */
270 : uint8_t *dynamic_page_bitmap;
271 :
272 : /*
273 : * The array of dynamic_regions is maintained in sorted order
274 : * Accesses must be protected by dynamic_load_mutex
275 : */
276 : struct NaClDynamicRegion *dynamic_regions;
277 : int num_dynamic_regions;
278 : int dynamic_regions_allocated;
279 :
280 : /*
281 : * These variables are used for caching mapped writable views of the
282 : * dynamic text segment. See CachedMapWritableText in nacl_text.c.
283 : * Accesses must be protected by dynamic_load_mutex
284 : */
285 : uint32_t dynamic_mapcache_offset;
286 : uint32_t dynamic_mapcache_size;
287 : uintptr_t dynamic_mapcache_ret;
288 :
289 : /*
290 : * Monotonically increasing generation number used for deletion
291 : * Accesses must be protected by dynamic_load_mutex
292 : */
293 : int dynamic_delete_generation;
294 :
295 :
296 : int running;
297 : int exit_status;
298 :
299 :
300 : NaClCPUFeatures cpu_features;
301 : int ignore_validator_result;
302 : int skip_validator;
303 : int validator_stub_out_mode;
304 :
305 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
306 : uint16_t code_seg_sel;
307 : uint16_t data_seg_sel;
308 : #endif
309 :
310 : uintptr_t break_addr; /* user addr */
311 : /* data_end <= break_addr is an invariant */
312 :
313 : /*
314 : * Thread table lock threads_mu is higher in the locking order than
315 : * the thread locks, i.e., threads_mu must be acqured w/o holding
316 : * any per-thread lock (natp->mu).
317 : */
318 : struct NaClMutex threads_mu;
319 : struct NaClCondVar threads_cv;
320 : struct DynArray threads; /* NaClAppThread pointers */
321 : int num_threads; /* number actually running */
322 :
323 : struct NaClMutex desc_mu;
324 : struct DynArray desc_tbl; /* NaClDesc pointers */
325 :
326 : int enable_debug_stub;
327 : struct NaClDebugCallbacks *debug_stub_callbacks;
328 : struct NaClMutex exception_mu;
329 : uint32_t exception_handler;
330 : int enable_exception_handling;
331 : };
332 :
333 :
334 :
335 : void NaClAppIncrVerbosity(void);
336 :
337 : /*
338 : * Initializes a NaCl application with the default parameters
339 : * and the specified syscall table.
340 : *
341 : * nap is a pointer to the NaCl object that is being filled in.
342 : *
343 : * table is the NaCl syscall table. The syscall table must contain at least
344 : * NACL_MAX_SYSCALLS valid entries.
345 : *
346 : * Caution! Syscall handlers must be extremely careful with respect to
347 : * argument validation, including time-of-check vs time-of-use defense, etc.
348 : */
349 : int NaClAppWithSyscallTableCtor(struct NaClApp *nap,
350 : struct NaClSyscallTableEntry *table) NACL_WUR;
351 :
352 : int NaClAppCtor(struct NaClApp *nap) NACL_WUR;
353 :
354 : /*
355 : * Loads a NaCl ELF file into memory in preparation for running it.
356 : *
357 : * gp is a pointer to a generic I/O object and should be a GioMem with
358 : * a memory buffer containing the file read entirely into memory if
359 : * the file system might be subject to race conditions (e.g., another
360 : * thread / process might modify a downloaded NaCl ELF file while we
361 : * are loading it here).
362 : *
363 : * nap is a pointer to the NaCl object that is being filled in. it
364 : * should be properly constructed via NaClAppCtor.
365 : *
366 : * return value: one of the LOAD_* values defined in
367 : * nacl_error_code.h. TODO: add some error detail string and hang
368 : * that off the nap object, so that more details are available w/o
369 : * incrementing verbosity (and polluting stdout).
370 : *
371 : * note: it may be necessary to flush the icache if the memory
372 : * allocated for use had already made it into the icache from another
373 : * NaCl application instance, and the icache does not detect
374 : * self-modifying code / data writes and automatically invalidate the
375 : * cache lines.
376 : */
377 : NaClErrorCode NaClAppLoadFile(struct Gio *gp,
378 : struct NaClApp *nap) NACL_WUR;
379 :
380 : NaClErrorCode NaClAppLoadFileDynamically(struct NaClApp *nap,
381 : struct Gio *gio_file) NACL_WUR;
382 :
383 : size_t NaClAlignPad(size_t val,
384 : size_t align);
385 :
386 : void NaClAppPrintDetails(struct NaClApp *nap,
387 : struct Gio *gp);
388 :
389 : NaClErrorCode NaClLoadImage(struct Gio *gp,
390 : struct NaClApp *nap) NACL_WUR;
391 :
392 : int NaClValidateCode(struct NaClApp *nap,
393 : uintptr_t guest_addr,
394 : uint8_t *data,
395 : size_t size) NACL_WUR;
396 :
397 : /*
398 : * Validates that the code found at data_old can safely be replaced with
399 : * the code found at data_new.
400 : */
401 : int NaClValidateCodeReplacement(struct NaClApp *nap,
402 : uintptr_t guest_addr,
403 : uint8_t *data_old,
404 : uint8_t *data_new,
405 : size_t size);
406 :
407 : /*
408 : * Copies code from data_new to data_old in a thread-safe way
409 : */
410 : int NaClCopyCode(struct NaClApp *nap, uintptr_t guest_addr,
411 : uint8_t *data_old, uint8_t *data_new,
412 : size_t size);
413 :
414 : NaClErrorCode NaClValidateImage(struct NaClApp *nap) NACL_WUR;
415 :
416 :
417 : int NaClAddrIsValidEntryPt(struct NaClApp *nap,
418 : uintptr_t addr);
419 :
420 : /*
421 : * Takes ownership of descriptor, i.e., when NaCl app closes, it's gone.
422 : */
423 : void NaClAddHostDescriptor(struct NaClApp *nap,
424 : int host_os_desc,
425 : int mode,
426 : int nacl_desc);
427 :
428 : /*
429 : * Takes ownership of handle.
430 : */
431 : void NaClAddImcHandle(struct NaClApp *nap,
432 : NaClHandle h,
433 : int nacl_desc);
434 :
435 : /*
436 : * Launch system-level service threads. After this, access to the
437 : * NaClApp object must be done in a thread-safe manner, using nap->mu
438 : * etc, or access only read-only data.
439 : *
440 : * NB: the "secure command channel" thread should have already started
441 : * (if enabled); that thread must take care to not race with the main
442 : * thread that is continuing to set up the NaCl module as well.
443 : */
444 : int NaClAppLaunchServiceThreads(struct NaClApp *nap);
445 :
446 : /*
447 : * Report the low eight bits of |exit_status| via the reverse channel
448 : * in |nap|, if one exists, to whomever is interested. This usually
449 : * involves an RPC. Returns true if successfully reported.
450 : *
451 : * Also mark nap's exit_status and running member variables, announce
452 : * via condvar that the nexe should be considered no longer running.
453 : *
454 : * Returns true (non-zero) if exit status was reported via the reverse
455 : * channel, and false (0) otherwise.
456 : */
457 : int NaClReportExitStatus(struct NaClApp *nap, int exit_status);
458 :
459 : /*
460 : * Used to launch the main thread. NB: calling thread may in the
461 : * future become the main NaCl app thread, and this function will
462 : * return only after the NaCl app main thread exits. In such an
463 : * alternative design, NaClWaitForMainThreadToExit will become a
464 : * no-op.
465 : */
466 : int NaClCreateMainThread(struct NaClApp *nap,
467 : int argc,
468 : char **argv,
469 : char const *const *envp) NACL_WUR;
470 :
471 : int NaClWaitForMainThreadToExit(struct NaClApp *nap);
472 :
473 : /*
474 : * Register the integrated runtime (IRT) library file for use by
475 : * NaClMainForChromium(). This takes a file descriptor, even on
476 : * Windows (where file descriptors are emulated by the C runtime
477 : * library).
478 : */
479 : void NaClSetIrtFileDesc(int fd);
480 :
481 : void NaClMainForChromium(int handle_count, const NaClHandle *handles,
482 : int debug);
483 :
484 : /*
485 : * Used by syscall code.
486 : */
487 : int32_t NaClCreateAdditionalThread(struct NaClApp *nap,
488 : uintptr_t prog_ctr,
489 : uintptr_t stack_ptr,
490 : uintptr_t sys_tls,
491 : uint32_t user_tls2) NACL_WUR;
492 :
493 : void NaClLoadTrampoline(struct NaClApp *nap);
494 :
495 : void NaClLoadSpringboard(struct NaClApp *nap);
496 :
497 : static const uintptr_t kNaClBadAddress = (uintptr_t) -1;
498 :
499 : #include "native_client/src/trusted/service_runtime/sel_ldr-inl.h"
500 :
501 : /*
502 : * Looks up a descriptor in the open-file table. An additional
503 : * reference is taken on the returned NaClDesc object (if non-NULL).
504 : * The caller is responsible for invoking NaClDescUnref() on it when
505 : * done.
506 : */
507 : struct NaClDesc *NaClGetDesc(struct NaClApp *nap,
508 : int d);
509 :
510 : /*
511 : * Takes ownership of ndp.
512 : */
513 : void NaClSetDesc(struct NaClApp *nap,
514 : int d,
515 : struct NaClDesc *ndp);
516 :
517 :
518 : int32_t NaClSetAvail(struct NaClApp *nap,
519 : struct NaClDesc *ndp);
520 :
521 : /*
522 : * Versions that are called while already holding the desc_mu lock
523 : */
524 : struct NaClDesc *NaClGetDescMu(struct NaClApp *nap,
525 : int d);
526 :
527 : void NaClSetDescMu(struct NaClApp *nap,
528 : int d,
529 : struct NaClDesc *ndp);
530 :
531 : int32_t NaClSetAvailMu(struct NaClApp *nap,
532 : struct NaClDesc *ndp);
533 :
534 :
535 : int NaClAddThread(struct NaClApp *nap,
536 : struct NaClAppThread *natp);
537 :
538 : int NaClAddThreadMu(struct NaClApp *nap,
539 : struct NaClAppThread *natp);
540 :
541 : void NaClRemoveThread(struct NaClApp *nap,
542 : int thread_num);
543 :
544 : void NaClRemoveThreadMu(struct NaClApp *nap,
545 : int thread_num);
546 :
547 : struct NaClAppThread *NaClGetThreadMu(struct NaClApp *nap,
548 : int thread_num);
549 :
550 : void NaClAppInitialDescriptorHookup(struct NaClApp *nap);
551 :
552 : void NaClAppVmmapUpdate(struct NaClApp *nap,
553 : uintptr_t page_num,
554 : size_t npages,
555 : int prot,
556 : struct NaClMemObj *nmop,
557 : int remove);
558 :
559 : uintptr_t NaClAppVmmapFindSpace(struct NaClApp *nap,
560 : int num_pages);
561 :
562 : uintptr_t NaClAppVmmapFindMapSpace(struct NaClApp *nap,
563 : int num_pages);
564 :
565 : void NaClCreateServiceSocket(struct NaClApp *nap);
566 :
567 : void NaClSendServiceAddressTo(struct NaClApp *nap,
568 : int desc);
569 :
570 : void NaClSecureCommandChannel(struct NaClApp *nap);
571 :
572 : int NaClSecureReverseClientInsertHandler(
573 : struct NaClSecureReverseClient *self,
574 : void (*handler)(
575 : void *handler_state,
576 : struct NaClThreadInterface *thread_if,
577 : struct NaClDesc *new_conn),
578 : void *handler_state) NACL_WUR;
579 :
580 : NaClErrorCode NaClWaitForLoadModuleStatus(struct NaClApp *nap) NACL_WUR;
581 :
582 : NaClErrorCode NaClWaitForStartModuleCommand(struct NaClApp *nap) NACL_WUR;
583 :
584 : /*
585 : * NaClBlockIfCommandChannelExists is used during error exit. If
586 : * there is a secure command channel, we sent an RPC reply with the
587 : * reason that the nexe was rejected. If we exit immediately, that
588 : * reply may still be in-flight and the various channel closure (esp
589 : * reverse channels, if those were set up) may be detected first by
590 : * the controlling process on the other end of the command channel or
591 : * reverse channel. When channel closure wins the race against the
592 : * RPC reply, it would result in a crash being reported, rather than
593 : * the error code carried in the RPC reply. We want to ensure that
594 : * the RPC reply to get processed. Instead of allowing the service
595 : * runtime process to exit, we block the main thread and wait for the
596 : * hard-shutdown on the command channel or command channel closure.
597 : *
598 : * If there is no command channel, NaClBlockIfCommandChannelExists
599 : * just returns immediately.
600 : */
601 : void NaClBlockIfCommandChannelExists(struct NaClApp *nap);
602 :
603 : void NaClFillMemoryRegionWithHalt(void *start, size_t size);
604 :
605 : void NaClFillTrampolineRegion(struct NaClApp *nap);
606 :
607 : void NaClFillEndOfTextRegion(struct NaClApp *nap);
608 :
609 : #if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 \
610 : && NACL_BUILD_SUBARCH == 32 && __PIC__)
611 :
612 : int NaClMakePcrelThunk(struct NaClApp *nap);
613 :
614 : #endif
615 :
616 : #if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 \
617 : && NACL_BUILD_SUBARCH == 64)
618 :
619 : int NaClMakeDispatchThunk(struct NaClApp *nap);
620 : void NaClPatchOneTrampolineCall(uintptr_t call_target_addr,
621 : uintptr_t target_addr);
622 :
623 : #endif
624 :
625 : #if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 \
626 : && NACL_BUILD_SUBARCH == 32)
627 :
628 : void NaClPatchDebuggerInfo(struct NaClApp *nap);
629 :
630 : #endif
631 :
632 : void NaClPatchOneTrampoline(struct NaClApp *nap,
633 : uintptr_t target_addr);
634 : /*
635 : * target is an absolute address in the source region. the patch code
636 : * will figure out the corresponding address in the destination region
637 : * and modify as appropriate. this makes it easier to specify, since
638 : * the target is typically the address of some symbol from the source
639 : * template.
640 : */
641 : struct NaClPatch {
642 : uintptr_t target;
643 : uint64_t value;
644 : };
645 :
646 : struct NaClPatchInfo {
647 : uintptr_t dst;
648 : uintptr_t src;
649 : size_t nbytes;
650 :
651 : struct NaClPatch *abs16;
652 : size_t num_abs16;
653 :
654 : struct NaClPatch *abs32;
655 : size_t num_abs32;
656 :
657 : struct NaClPatch *abs64;
658 : size_t num_abs64;
659 :
660 : #if NACL_TARGET_SUBARCH == 32
661 : uintptr_t *rel32;
662 : size_t num_rel32;
663 : #endif
664 :
665 : uintptr_t *rel64;
666 : size_t num_rel64;
667 : };
668 :
669 : struct NaClPatchInfo *NaClPatchInfoCtor(struct NaClPatchInfo *self);
670 :
671 : void NaClApplyPatchToMemory(struct NaClPatchInfo *patch);
672 :
673 : int NaClThreadContextCtor(struct NaClThreadContext *ntcp,
674 : struct NaClApp *nap,
675 : nacl_reg_t prog_ctr,
676 : nacl_reg_t stack_ptr,
677 : uint32_t tls_info);
678 :
679 : void NaClThreadContextDtor(struct NaClThreadContext *ntcp);
680 :
681 : void NaClVmHoleWaitToStartThread(struct NaClApp *nap);
682 :
683 : void NaClVmHoleThreadStackIsSafe(struct NaClApp *nap);
684 :
685 : void NaClGdbHook(struct NaClApp const *nap);
686 :
687 : #if NACL_WINDOWS
688 :
689 : void NaClUntrustedThreadsSuspend(struct NaClApp *nap);
690 : void NaClUntrustedThreadsResume(struct NaClApp *nap);
691 :
692 : #else
693 :
694 : /*
695 : * Suspending untrusted threads is only needed for preventing mmap
696 : * races on Windows, so these are no-ops on other platforms.
697 : */
698 :
699 7 : static INLINE void NaClUntrustedThreadsSuspend(struct NaClApp *nap) {
700 : UNREFERENCED_PARAMETER(nap);
701 7 : }
702 :
703 7 : static INLINE void NaClUntrustedThreadsResume(struct NaClApp *nap) {
704 : UNREFERENCED_PARAMETER(nap);
705 7 : }
706 :
707 : #endif
708 :
709 : #if NACL_LINUX
710 : void handle_r_debug(const char *switch_value, char *argv0);
711 : #endif
712 :
713 : EXTERN_C_END
714 :
715 : #endif /* NATIVE_CLIENT_SRC_TRUSTED_SERVICE_RUNTIME_SEL_LDR_H_ */
|