2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * NaCl Simple/secure ELF loader (NaCl SEL).
35 * This loader can only process NaCl object files as produced using
36 * the NaCl toolchain. Other ELF files will be rejected.
38 * The primary function, NaClAppLoadFile, parses an ELF file,
39 * allocates memory, loads the relocatable image from the ELF file
40 * into memory, and performs relocation. NaClAppRun runs the
43 * This loader is written in C so that it can be used by C-only as
44 * well as C++ applications. Other languages should also be able to
45 * use their foreign-function interfaces to invoke C code.
47 * This loader must be part of the NaCl TCB, since it directly handles
48 * externally supplied input (the ELF file). Any security
49 * vulnerabilities in handling the ELF image, e.g., buffer or integer
50 * overflows, can put the application at risk.
53 #ifndef SERVICE_RUNTIME_SEL_LDR_H__
54 #define SERVICE_RUNTIME_SEL_LDR_H__ 1
56 #include "native_client/include/nacl_platform.h"
57 #include "native_client/include/portability.h"
58 #include "native_client/include/nacl_base.h"
60 #include "native_client/service_runtime/dyn_array.h"
61 #include "native_client/service_runtime/gio.h"
62 #include "native_client/service_runtime/nacl_config.h"
63 #include "native_client/service_runtime/nacl_log.h"
64 #include "native_client/service_runtime/nacl_sync.h"
65 #include "native_client/service_runtime/nacl_sync_queue.h"
66 #include "native_client/service_runtime/nacl_desc_base.h"
67 #include "native_client/service_runtime/sel_mem.h"
68 #include "native_client/service_runtime/sel_util.h"
70 #include "native_client/service_runtime/nacl_error_code.h"
72 #include "native_client/include/portability.h"
74 #include "native_client/intermodule_comm/nacl_imc_c.h"
78 #define NACL_SERVICE_PORT_DESCRIPTOR 3
79 #define NACL_SERVICE_ADDRESS_DESCRIPTOR 4
81 #define NACL_MAX_ADDR_BITS (8 + 20)
82 /* wp: NACL_MAX_ADDR_BITS < 32, see NaClAppLoadFile */
83 #define NACL_DEFAULT_ENTRY_PT "NaClMain"
86 * the extra space for the trampoline syscall code and the thread
87 * contexts must be a multiple of the page size.
89 * TODO: leave an inaccessible page at page 0 to catch null
90 * pointers, so the first syscall will then be at page 1.
92 * TODO: change to trampoline shift of 16 (64K)
94 #define NACL_TRAMPOLINE_SHIFT 16
95 #define NACL_TRAMPOLINE_SIZE (1 << NACL_TRAMPOLINE_SHIFT)
96 #define NACL_THREAD_CTX_SIZE (64 << 10)
98 #define NACL_DEFAULT_ALLOC_MAX (32 << 20) /* total brk and mmap allocs */
99 #define NACL_DEFAULT_STACK_MAX (16 << 20) /* main thread stack */
101 #define NACL_NOOP_OPCODE 0x90
102 #define NACL_HALT_OPCODE 0xf4
105 * Finds the lowest 1 bit in PF_MASKOS. Assumes that at least one
106 * bit is set, and that this bit is not the highest-order bit.
108 * Let us denote PF_MASKOS by n. Assume n \ne 2^{31}. Let the k^{th}
109 * bit be the lowest order bit that is set, i.e.,
110 * n = m \cdot 2^{k+1} + 2^k, with k,m integers, m \ge 0, and 0 \le k < 31.
111 * then (here lhs is C notation, rhs is LaTeX notation):
112 * n ^ (n-1) = (m \cdot 2^{k+1} + 2^k)
113 * \oplus (m \dot 2^{k+1} + 2^{k-1} + \ldots + 1)
114 * = 2^k + 2^{k-1} + \ldots + 1
117 * ((n ^ (n-1)) + 1U) = 2^{k+1}, (since k < 31, no overflow occurs) and
118 * ((n ^ (n-1)) + 1U) >> 1 = 2^k. QED.
120 #define PF_OS_WILL_LOAD (((PF_MASKOS ^ (PF_MASKOS-1)) + 1U) >> 1)
121 #if PF_MASKOS == (1 << 31)
122 # error "PF_MASKOS too large, invariant needed for PF_OS_WILL_LOAD violated"
126 #define WINDOWS_EXCEPTION_TRY do { __try {
127 #define WINDOWS_EXCEPTION_CATCH } __except(EXCEPTION_EXECUTE_HANDLER) { \
129 "Unhandled Windows exception\n"); \
134 #define WINDOWS_EXCEPTION_TRY do {
135 #define WINDOWS_EXCEPTION_CATCH } while(0)
138 struct NaClAppThread
;
142 * public, user settable.
145 uint32_t max_data_alloc
, stack_size
;
147 * max_data_alloc controls how much total data memory can be
148 * allocated to the NaCl process; this is initialized data,
149 * uninitialized data, and heap and affects the brk system call.
150 * the text size and rodata size are not included, even though in
151 * NaCl the text and rodata pages are also backed by the pager
152 * since due to relocation the text pages and rodata contents
153 * cannot simply be memory mapped from the executable.
155 * stack_size is the maximum size of the (main) stack. The stack
156 * memory is eager allocated (mapped in w/o MAP_NORESERVE) so
157 * there must be enough swap space; page table entries are not
158 * populated (no MAP_POPULATE), so actual accesses will likely
162 /* determined at load time; OS-determined */
164 uintptr_t data_mem_start
;
165 uintptr_t xlate_base
;
166 uintptr_t code_mem_start
;
168 /* only used for ET_EXEC: for CS restriction */
169 uint32_t text_region_end
; /* relative address */
172 /* see break_addr below */
177 * Alignment boundary for validation (16 or 32).
185 * phdrs and sections are mutually exclusive.
187 * phdrs non-NULL means that an ELF executable -- with starting text
188 * address of NACL_TRAMPOLINE_SIZE -- is used. sections headers are
189 * still loaded, for things like bss size. ???? TODO
191 * when phdrs is NULL, a relocatable object was used and sections
192 * will be non-NULL, with the loader performing relocation as part
193 * of the image load. This is insufficient for C++ since preinit
194 * and init code is not executed, so global constructors aren't run,
195 * and multiple section groups for template instantiation are not
196 * handled properly, among other issues.
198 Elf32_Phdr
*phdrs
; /* elf_hdr.e_phnum entries */
200 /* common to both ELF executables and relocatable load images */
202 uintptr_t springboard_addr
; /* relative to mem_start */
204 * springboard code addr for context switching into app sandbox, relative
209 * The socket at which the app should be accepting connections. The
210 * corresponding socket address are made available by the JavaScript
211 * bridge to other NaCl modules.
213 struct NaClDesc
*service_port
;
214 struct NaClDesc
*service_address
;
217 struct NaClCondVar cv
;
219 * runtime info below, thread state, etc; initialized only when app
220 * is run. Mutex mu protects access to mem_map and other member
221 * variables while the application is running and may be
222 * multithreaded; thread, desc members have their own locks. At
223 * other times it is assumed that only one thread is
224 * constructing/loading the NaClApp and that no mutual exclusion is
229 * memory map is in user addresses.
231 struct NaClVmmap mem_map
;
237 * enforce that some "special" syscalls may only be made from the
238 * main/privileged thread
240 int restrict_to_main_thread
;
241 /* all threads enqueue the "special" syscalls to the work queue */
242 struct NaClSyncQueue work_queue
;
244 uint16_t code_seg_sel
;
245 uint16_t data_seg_sel
;
247 uintptr_t break_addr
; /* user addr */
248 /* data_end <= break_addr is an invariant */
250 int freeze_thread_ops
;
251 /* used when process is killed, or when address space move is needed */
254 * Thread table lock threads_mu is higher in the locking order than
255 * the thread locks, i.e., threads_mu must be acqured w/o holding
256 * any per-thread lock (natp->mu).
258 struct NaClMutex threads_mu
;
259 struct NaClCondVar threads_cv
;
260 struct DynArray threads
; /* NaClAppThread pointers */
261 int num_threads
; /* number actually running */
263 struct NaClMutex desc_mu
;
264 struct DynArray desc_tbl
; /* NaClDesc pointers */
267 #define NACL_MAX_PROGRAM_HEADERS 128
269 enum NaClPhdrCheckAction
{
272 PCA_IGNORE
, /* ignore this segment. currently used only for PT_PHDR. */
275 struct NaClPhdrChecks
{
277 Elf32_Word p_flags
; /* rwx */
278 enum NaClPhdrCheckAction action
;
279 int required
; /* only for text for now */
280 Elf32_Word p_vaddr
; /* if non-zero, vaddr must be this */
284 void NaClAppIncrVerbosity(void);
286 int NaClAppCtor(struct NaClApp
*nap
);
288 void NaClAppDtor(struct NaClApp
*nap
);
290 void NaClAppFreeAllMemory(struct NaClApp
*nap
);
293 * Loads a NaCl ELF file into memory in preparation for running it.
295 * gp is a pointer to a generic I/O object and should be a GioMem with
296 * a memory buffer containing the file read entirely into memory if
297 * the file system might be subject to race conditions (e.g., another
298 * thread / process might modify a downloaded NaCl ELF file while we
299 * are loading it here).
301 * nap is a pointer to the NaCl object that is being filled in. it
302 * should be properly constructed via NaClAppCtor.
304 * return value: one of the LOAD_* values below. TODO: add some error
305 * detail string and hang that off the nap object, so that more
306 * details are available w/o incrementing verbosity (and polluting
309 * note: it may be necessary to flush the icache if the memory
310 * allocated for use had already made it into the icache from another
311 * NaCl application instance, and the icache does not detect
312 * self-modifying code / data writes and automatically invalidate the
315 NaClErrorCode
NaClAppLoadFile(struct Gio
*gp
,
316 struct NaClApp
*nap
);
318 size_t NaClAlignPad(size_t val
,
321 void NaClAppPrintDetails(struct NaClApp
*nap
,
324 uint32_t NaClLoad32(uintptr_t addr
);
326 void NaClStore32(uintptr_t addr
,
329 NaClErrorCode
NaClLoadImage(struct Gio
*gp
,
330 struct NaClApp
*nap
);
332 void NaClIgnoreValidatorResult();
333 NaClErrorCode
NaClValidateImage(struct NaClApp
*nap
);
336 int NaClAddrIsValidEntryPt(struct NaClApp
*nap
,
340 * Takes ownership of descriptor, i.e., when NaCl app closes, it's gone.
342 void NaClAddHostDescriptor(struct NaClApp
*nap
,
348 * Takes ownership of handle.
350 void NaClAddImcHandle(struct NaClApp
*nap
,
354 void NaClAddImcAddr(struct NaClApp
*nap
,
355 struct NaClSocketAddress
const *addr
,
359 * Used to launch the main thread. NB: calling thread may in the
360 * future become the main NaCl app thread, and this function will
361 * return only after the NaCl app main thread exits. In such an
362 * alternative design, NaClWaitForMainThreadToExit will become a
365 int NaClCreateMainThread(struct NaClApp
*nap
,
370 int NaClWaitForMainThreadToExit(struct NaClApp
*nap
);
373 * Used by syscall code.
375 int32_t NaClCreateAdditionalThread(struct NaClApp
*nap
,
381 void NaClLoadTrampoline(struct NaClApp
*nap
);
383 void NaClLoadSpringboard(struct NaClApp
*nap
);
385 static const uintptr_t kNaClBadAddress
= (uintptr_t) -1;
388 * Routines to translate addresses between user and "system" or
389 * service runtime addresses. the *Addr* versions will return
390 * kNaClBadAddress if the usr address is outside of the user address
391 * space, e.g., if the input addresses for *UserToSys* is outside of
392 * (1<<nap->addr_bits), and correspondingly for *SysToUser* if the
393 * input system address does not correspond to a user address.
394 * Generally, the *Addr* versions are used when the addresses come
395 * from untrusted usre code, and kNaClBadAddress would translate to an
396 * EINVAL return from a syscall. The *Range code ensures that the
397 * entire address range is in the user address space.
399 * Note that just because an address is within the address space, it
400 * doesn't mean that it is safe to acceess the memory: the page may be
401 * protected against access.
403 * The non-*Addr* versions abort the program rather than return an
408 * address translation routines. after a NaClApp is started, the
409 * member variables accessed by these routines are read-only, so no
410 * locking is needed to use these functions, as long as the NaClApp
411 * structure doesn't get destructed/deallocated.
413 * the first is used internally when a NULL pointer is okay, typically
414 * for address manipulation.
416 * the next two are for syscalls to do address translation, e.g., for
417 * system calls; -1 indicates an error, so the syscall can return
418 * EINVAL or EFAULT or whatever is appropriate.
420 * the latter two interfaces are for use everywhere else in the loader
421 * / service runtime and will log a fatal error and abort the process
422 * when an error is detected. (0 is not a good error indicator, since
423 * 0 is a valid user address.)
426 static INLINE
uintptr_t NaClUserToSysAddrNullOkay(struct NaClApp
*nap
,
429 if (uaddr
>= (1U << nap
->addr_bits
)) {
430 return kNaClBadAddress
;
432 return uaddr
+ nap
->xlate_base
;
435 static INLINE
uintptr_t NaClUserToSysAddr(struct NaClApp
*nap
,
438 if (0 == uaddr
|| uaddr
>= (1U << nap
->addr_bits
)) {
439 return kNaClBadAddress
;
441 return uaddr
+ nap
->xlate_base
;
444 static INLINE
uintptr_t NaClSysToUserAddr(struct NaClApp
*nap
,
447 if (sysaddr
< nap
->data_mem_start
||
448 sysaddr
>= nap
->data_mem_start
+ (1U << nap
->addr_bits
)) {
449 return kNaClBadAddress
;
451 return sysaddr
- nap
->xlate_base
;
454 static INLINE
uintptr_t NaClUserToSysAddrRange(struct NaClApp
*nap
,
461 return kNaClBadAddress
;
463 end_addr
= uaddr
+ count
;
464 if (end_addr
< uaddr
) {
465 /* unsigned wraparound */
466 return kNaClBadAddress
;
468 if (end_addr
>= (1U << nap
->addr_bits
)) {
469 return kNaClBadAddress
;
471 return uaddr
+ nap
->xlate_base
;
474 static INLINE
uintptr_t NaClUserToSys(struct NaClApp
*nap
,
477 if (0 == uaddr
|| uaddr
>= (1U << nap
->addr_bits
)) {
479 "NaClUserToSys: uaddr 0x%08x, addr space %u bits",
480 uaddr
, nap
->addr_bits
);
482 return uaddr
+ nap
->xlate_base
;
485 static INLINE
uintptr_t NaClSysToUser(struct NaClApp
*nap
,
488 if (sysaddr
< nap
->data_mem_start
||
489 sysaddr
>= nap
->data_mem_start
+ (1U << nap
->addr_bits
)) {
491 "NaclSysToUser: sysaddr 0x%08x, mem_start 0x%08x,"
492 " addr space %d bits",
493 sysaddr
, nap
->data_mem_start
, nap
->addr_bits
);
495 return sysaddr
- nap
->xlate_base
;
499 * Looks up a descriptor in the open-file table. An additional
500 * reference is taken on the returned NaClDesc object (if non-NULL).
501 * The caller is responsible for invoking NaClDescUnref() on it when
504 struct NaClDesc
*NaClGetDesc(struct NaClApp
*nap
,
508 * Takes ownership of ndp.
510 void NaClSetDesc(struct NaClApp
*nap
,
512 struct NaClDesc
*ndp
);
515 int NaClSetAvail(struct NaClApp
*nap
,
516 struct NaClDesc
*ndp
);
519 * Versions that are called while already holding the desc_mu lock
521 struct NaClDesc
*NaClGetDescMu(struct NaClApp
*nap
,
524 void NaClSetDescMu(struct NaClApp
*nap
,
526 struct NaClDesc
*ndp
);
528 int NaClSetAvailMu(struct NaClApp
*nap
,
529 struct NaClDesc
*ndp
);
532 int NaClAddThread(struct NaClApp
*nap
,
533 struct NaClAppThread
*natp
);
535 int NaClAddThreadMu(struct NaClApp
*nap
,
536 struct NaClAppThread
*natp
);
538 void NaClRemoveThread(struct NaClApp
*nap
,
541 void NaClRemoveThreadMu(struct NaClApp
*nap
,
544 struct NaClAppThread
*NaClGetThreadMu(struct NaClApp
*nap
,
547 void NaClAppVmmapUpdate(struct NaClApp
*nap
,
551 struct NaClMemObj
*nmop
,
554 uintptr_t NaClAppVmmapFindSpace(struct NaClApp
*nap
,
557 uintptr_t NaClAppVmmapFindMapSpace(struct NaClApp
*nap
,
560 void NaClCreateServiceSocket(struct NaClApp
*nap
);
562 void NaClSendServiceAddressTo(struct NaClApp
*nap
,
565 void NaClDumpServiceAddressTo(struct NaClApp
*nap
,