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).
36 #include "native_client/include/portability.h"
43 #include "native_client/include/nacl_elf.h"
44 #include "native_client/service_runtime/sel_memory.h"
45 #include "native_client/service_runtime/sel_ldr.h"
46 #include "native_client/service_runtime/sel_util.h"
47 #include "native_client/service_runtime/sel_addrspace.h"
48 #include "native_client/service_runtime/nacl_app_thread.h"
49 #include "native_client/service_runtime/nacl_check.h"
50 #include "native_client/service_runtime/nacl_closure.h"
51 #include "native_client/service_runtime/nacl_sync_checked.h"
52 #include "native_client/service_runtime/nacl_sync_queue.h"
53 #include "native_client/service_runtime/nacl_time.h"
55 #include "native_client/service_runtime/tramp.h"
57 #define PTR_ALIGN_MASK ((sizeof(void *))-1)
60 * Other than empty segments, these are the only ones that are allowed.
62 struct NaClPhdrChecks nacl_phdr_check_data
[] = {
64 { PT_PHDR
, PF_R
, PCA_IGNORE
, 0, 0, },
66 { PT_LOAD
, PF_R
|PF_X
, PCA_TEXT_CHECK
, 1, NACL_TRAMPOLINE_SIZE
, },
68 { PT_LOAD
, PF_R
, PCA_NONE
, 0, 0, },
70 { PT_LOAD
, PF_R
|PF_W
, PCA_NONE
, 0, 0, },
71 /* tdata/tbss, part of data */
72 { PT_TLS
, PF_R
, PCA_SAVE_TLS_INFO
, 0, 0, },
74 * allow optional GNU stack permission marker, but require that the
75 * stack is non-executable.
77 { PT_GNU_STACK
, PF_R
|PF_W
, PCA_NONE
, 0, 0, },
80 NaClErrorCode
NaClProcessPhdrs(struct NaClApp
*nap
)
82 /* Scan phdrs and do sanity checks in-line. Verify that the load
83 * address is NACL_TRAMPOLINE_SIZE, that we have a single text
84 * segment. Data and TLS segments are not required, though it is
85 * hard to avoid with standard tools, but in any case there should
86 * be at most one each. Ensure that no segment's vaddr is outside
87 * of the address space. Ensure that PT_GNU_STACK is present, and
90 int seen_seg
[(sizeof nacl_phdr_check_data
91 / sizeof nacl_phdr_check_data
[0])];
97 memset(seen_seg
, 0, sizeof seen_seg
);
98 max_vaddr
= NACL_TRAMPOLINE_SIZE
;
100 * nacl_phdr_check_data is small, so O(|check_data| * nap->elf_hdr.e_phum)
103 for (segnum
= 0; segnum
< nap
->elf_hdr
.e_phnum
; ++segnum
) {
104 php
= &nap
->phdrs
[segnum
];
105 NaClLog(3, "Looking at segment %d, type 0x%x, p_flags 0x%x\n",
106 segnum
, php
->p_type
, php
->p_flags
);
107 php
->p_flags
&= ~PF_MASKOS
;
109 j
< sizeof nacl_phdr_check_data
/sizeof nacl_phdr_check_data
[0];
111 if (php
->p_type
== nacl_phdr_check_data
[j
].p_type
112 && php
->p_flags
== nacl_phdr_check_data
[j
].p_flags
) {
113 NaClLog(2, "Matched nacl_phdr_check_data[%"PRIdS
"]\n", j
);
115 NaClLog(2, "Segment %d is a type that has been seen\n", segnum
);
116 return LOAD_DUP_SEGMENT
;
120 if (PCA_IGNORE
== nacl_phdr_check_data
[j
].action
) {
121 NaClLog(3, "Ignoring\n");
125 if (0 != php
->p_memsz
) {
127 * We will load this segment later. Do the sanity checks.
129 if (0 != nacl_phdr_check_data
[j
].p_vaddr
130 && (nacl_phdr_check_data
[j
].p_vaddr
!= php
->p_vaddr
)) {
132 ("Segment %d: bad virtual address: 0x%08x,"
133 " expected 0x%08x\n"),
136 nacl_phdr_check_data
[j
].p_vaddr
);
137 return LOAD_SEGMENT_BAD_LOC
;
139 if (php
->p_vaddr
< NACL_TRAMPOLINE_SIZE
) {
140 NaClLog(2, "Segment %d: virtual address (0x%08x) too low\n",
143 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE
;
146 * integer overflow? Elf32_Addr and Elf32_Word are uint32_t,
147 * so the addition/comparison is well defined.
149 if (php
->p_vaddr
+ php
->p_memsz
< php
->p_vaddr
) {
151 "Segment %d: p_memsz caused integer overflow\n",
153 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE
;
155 if (php
->p_vaddr
+ php
->p_memsz
>= (1U << nap
->addr_bits
)) {
157 "Segment %d: too large, ends at 0x%08x\n",
159 php
->p_vaddr
+ php
->p_memsz
);
160 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE
;
162 if (php
->p_filesz
> php
->p_memsz
) {
164 ("Segment %d: file size 0x%08x larger"
165 " than memory size 0x%08x\n"),
169 return LOAD_SEGMENT_BAD_PARAM
;
172 php
->p_flags
|= PF_OS_WILL_LOAD
;
173 /* record our decision that we will load this segment */
176 * NACL_TRAMPOLINE_SIZE <= p_vaddr
177 * <= p_vaddr + p_memsz
178 * < (1U << nap->addr_bits)
180 if (max_vaddr
< php
->p_vaddr
+ php
->p_memsz
) {
181 max_vaddr
= php
->p_vaddr
+ php
->p_memsz
;
185 switch (nacl_phdr_check_data
[j
].action
) {
189 if (0 == php
->p_memsz
) {
190 return LOAD_BAD_ELF_TEXT
;
192 nap
->text_region_bytes
= php
->p_filesz
;
194 case PCA_SAVE_TLS_INFO
:
195 nap
->tls_start
= php
->p_vaddr
;
196 nap
->tls_size
= php
->p_memsz
;
204 /* segment not in nacl_phdr_check_data */
205 if (0 == php
->p_memsz
) {
206 NaClLog(3, "Segment %d zero size: ignored\n", segnum
);
210 "Segment %d is of unexpected type 0x%x, flag 0x%x\n",
214 return LOAD_BAD_SEGMENT
;
219 j
< sizeof nacl_phdr_check_data
/sizeof nacl_phdr_check_data
[0];
221 if (nacl_phdr_check_data
[j
].required
&& !seen_seg
[j
]) {
222 return LOAD_REQUIRED_SEG_MISSING
;
225 nap
->data_end
= nap
->break_addr
= max_vaddr
;
227 * Memory allocation will use NaClRoundPage(nap->break_addr), but
228 * the system notion of break is always an exact address. Even
229 * though we must allocate and make accessible multiples of pages,
230 * the linux-style brk system call (which returns current break on
231 * failure) permits an arbitrarily aligned address as argument.
237 NaClErrorCode
NaClAppLoadFile(struct Gio
*gp
,
240 NaClErrorCode ret
= LOAD_INTERNAL
;
241 NaClErrorCode subret
;
245 /* NACL_MAX_ADDR_BITS < 32 */
246 if (nap
->addr_bits
> NACL_MAX_ADDR_BITS
) {
247 ret
= LOAD_ADDR_SPACE_TOO_BIG
;
251 nap
->stack_size
= NaClRoundAllocPage(nap
->stack_size
);
253 /* nap->addr_bits <= NACL_MAX_ADDR_BITS < 32 */
254 if ((*gp
->vtbl
->Read
)(gp
,
257 != sizeof nap
->elf_hdr
) {
258 ret
= LOAD_READ_ERROR
;
262 #define DUMP(m,f) do { NaClLog(2, \
264 nap->elf_hdr.m); } while (0)
265 DUMP(e_ident
+1, ".3s");
267 DUMP(e_machine
, "#x");
268 DUMP(e_version
, "#x");
273 DUMP(e_ehsize
, "#x");
274 DUMP(e_phentsize
, "#x");
276 DUMP(e_shentsize
, "#x");
278 DUMP(e_shstrndx
, "#x");
280 NaClLog(2, "sizeof(Elf32_Ehdr) = %x\n", (int) sizeof nap
->elf_hdr
);
282 if (memcmp(nap
->elf_hdr
.e_ident
, ELFMAG
, SELFMAG
)) {
283 ret
= LOAD_BAD_ELF_MAGIC
;
286 if (ELFCLASS32
!= nap
->elf_hdr
.e_ident
[EI_CLASS
]) {
287 ret
= LOAD_NOT_32_BIT
;
290 if (ELFOSABI_NACL
!= nap
->elf_hdr
.e_ident
[EI_OSABI
]) {
291 NaClLog(LOG_ERROR
, "Expected OSABI %d, got %d\n",
293 nap
->elf_hdr
.e_ident
[EI_OSABI
]);
297 if (EF_NACL_ABIVERSION
!= nap
->elf_hdr
.e_ident
[EI_ABIVERSION
]) {
298 NaClLog(LOG_ERROR
, "Expected ABIVERSION %d, got %d\n",
300 nap
->elf_hdr
.e_ident
[EI_ABIVERSION
]);
304 if (ET_EXEC
!= nap
->elf_hdr
.e_type
) {
308 if (EM_386
!= nap
->elf_hdr
.e_machine
) {
309 ret
= LOAD_BAD_MACHINE
;
312 if (EV_CURRENT
!= nap
->elf_hdr
.e_version
) {
313 ret
= LOAD_BAD_ELF_VERS
;
316 nap
->entry_pt
= nap
->elf_hdr
.e_entry
;
318 if (nap
->elf_hdr
.e_flags
& EF_NACL_ALIGN_MASK
) {
319 unsigned long eflags
= nap
->elf_hdr
.e_flags
& EF_NACL_ALIGN_MASK
;
320 if (eflags
== EF_NACL_ALIGN_16
) {
321 nap
->align_boundary
= 16;
322 } else if (eflags
== EF_NACL_ALIGN_32
) {
323 nap
->align_boundary
= 32;
329 nap
->align_boundary
= 32;
332 /* read program headers */
333 if (nap
->elf_hdr
.e_phnum
> NACL_MAX_PROGRAM_HEADERS
) {
334 ret
= LOAD_TOO_MANY_SECT
; /* overloaded */
338 nap
->phdrs
= malloc(nap
->elf_hdr
.e_phnum
* sizeof nap
->phdrs
[0]);
340 ret
= LOAD_NO_MEMORY
;
343 if (nap
->elf_hdr
.e_phentsize
< sizeof nap
->phdrs
[0]) {
347 for (cur_ph
= 0; cur_ph
< nap
->elf_hdr
.e_phnum
; ++cur_ph
) {
348 if ((*gp
->vtbl
->Seek
)(gp
,
350 + cur_ph
* nap
->elf_hdr
.e_phentsize
,
355 if ((*gp
->vtbl
->Read
)(gp
,
357 sizeof nap
->phdrs
[0])
358 != sizeof nap
->phdrs
[0]) {
362 #define DUMP(mem) do {\
363 NaClLog(2, "%s: %x\n", #mem, nap->phdrs[cur_ph].mem); \
372 NaClLog(2, " (%s %s %s)\n",
373 (nap
->phdrs
[cur_ph
].p_flags
& PF_R
) ? "PF_R" : "",
374 (nap
->phdrs
[cur_ph
].p_flags
& PF_W
) ? "PF_W" : "",
375 (nap
->phdrs
[cur_ph
].p_flags
& PF_X
) ? "PF_X" : "");
382 * We need to determine the size of the CS region. (The DS and SS
383 * region sizes are obvious -- the entire application address
384 * space.) NaClProcessPhdrs will figure out nap->text_region_bytes.
387 subret
= NaClProcessPhdrs(nap
);
388 if (subret
!= LOAD_OK
) {
393 if (!NaClAddrIsValidEntryPt(nap
, nap
->entry_pt
)) {
394 ret
= LOAD_BAD_ENTRY
;
398 NaClLog(2, "Allocating address space\n");
399 subret
= NaClAllocAddrSpace(nap
);
400 if (subret
!= LOAD_OK
) {
405 NaClLog(2, "Loading into memory\n");
406 subret
= NaClLoadImage(gp
, nap
);
407 if (subret
!= LOAD_OK
) {
412 NaClLog(2, "Validating image\n");
413 subret
= NaClValidateImage(nap
);
414 if (subret
!= LOAD_OK
) {
419 NaClLog(2, "Installing trampoline\n");
421 NaClLoadTrampoline(nap
);
423 NaClLog(2, "Installing springboard\n");
425 NaClLoadSpringboard(nap
);
427 NaClLog(2, "Applying memory protection\n");
429 subret
= NaClMemoryProtection(nap
);
430 if (subret
!= LOAD_OK
) {
440 int NaClAddrIsValidEntryPt(struct NaClApp
*nap
,
443 if (0 != (addr
& (nap
->align_boundary
- 1))) {
447 return addr
< NACL_TRAMPOLINE_SIZE
+ nap
->text_region_bytes
;
452 * argc > 0, argc and argv table is consistent
453 * envv may be NULL (this happens on MacOS/Cocoa
454 * if envv is non-NULL it is 'consistent', null terminated etc.
456 int NaClCreateMainThread(struct NaClApp
*nap
,
462 * Compute size of string tables for argv and envv
473 struct NaClAppThread
*natp
;
476 retval
= 0; /* fail */
483 for (pp
= envv
, envc
= 0; NULL
!= *pp
; ++pp
, ++envc
)
487 argv_len
= malloc(argc
* sizeof argv_len
[0]);
488 envv_len
= malloc(envc
* sizeof envv_len
[0]);
489 if (NULL
== argv_len
) {
492 if (NULL
== envv_len
&& 0 != envc
) {
498 for (i
= 0; i
< argc
; ++i
) {
499 argv_len
[i
] = strlen(argv
[i
]) + 1;
502 for (i
= 0; i
< envc
; ++i
) {
503 envv_len
[i
] = strlen(envv
[i
]) + 1;
507 size
+= (argc
+ envc
+ 4) * sizeof(char *) + sizeof(int);
509 size
= (size
+ PTR_ALIGN_MASK
) & ~PTR_ALIGN_MASK
;
511 if (size
> nap
->stack_size
) {
516 /* write strings and char * arrays to stack */
518 esp
= (nap
->mem_start
+ (1 << nap
->addr_bits
) - size
);
519 VCHECK(0 == (esp
& PTR_ALIGN_MASK
), ("esp not aligned: %08x\n", esp
));
522 strp
= p
+ (argc
+ envc
+ 4) * sizeof(char *) + sizeof(int);
524 #define BLAT(t, v) do { \
525 *(t *) p = (t) v; p += sizeof(t); \
530 for (i
= 0; i
< argc
; ++i
) {
531 BLAT(char *, NaClSysToUser(nap
, (uintptr_t) strp
));
532 strcpy(strp
, argv
[i
]);
537 for (i
= 0; i
< envc
; ++i
) {
538 BLAT(char *, NaClSysToUser(nap
, (uintptr_t) strp
));
539 strcpy(strp
, envv
[i
]);
543 /* Push an empty auxv for glibc support */
548 /* now actually spawn the thread */
549 natp
= malloc(sizeof *natp
);
556 /* e_entry is user addr */
557 if (!NaClAppThreadAllocSegCtor(natp
,
560 nap
->elf_hdr
.e_entry
,
561 NaClSysToUser(nap
, esp
),
562 NaClUserToSys(nap
, nap
->break_addr
),
569 * NB: Hereafter locking is required to access nap.
579 int NaClWaitForMainThreadToExit(struct NaClApp
*nap
)
581 struct NaClClosure
*work
;
583 while (NULL
!= (work
= NaClSyncQueueDequeue(&nap
->work_queue
))) {
584 NaClLog(3, "NaClWaitForMainThreadToExit: got work %08"PRIxPTR
"\n",
586 NaClLog(3, " invoking Run fn %08"PRIxPTR
"\n",
587 (uintptr_t) work
->vtbl
->Run
);
589 (*work
->vtbl
->Run
)(work
);
590 NaClLog(3, "... done\n");
593 NaClLog(3, " taking NaClApp lock\n");
594 NaClXMutexLock(&nap
->mu
);
595 NaClLog(3, " waiting for exit status\n");
596 while (nap
->running
) {
597 NaClCondVarWait(&nap
->cv
, &nap
->mu
);
600 * Some thread invoked the exit (exit_group) syscall.
603 return (nap
->exit_status
);
606 int32_t NaClCreateAdditionalThread(struct NaClApp
*nap
,
612 struct NaClAppThread
*natp
;
614 natp
= malloc(sizeof *natp
);
616 return -NACL_ABI_ENOMEM
;
618 if (!NaClAppThreadAllocSegCtor(natp
, nap
, 0, eip
, esp
, sys_tdb
, tdb_size
)) {
619 return -NACL_ABI_ENOMEM
;