Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(303)

Unified Diff: src/trusted/service_runtime/sel_ldr_standard.c

Issue 389022: first step in factoring out code dealing with elf into a separate library.... (Closed) Base URL: http://nativeclient.googlecode.com/svn/trunk/src/native_client/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/trusted/service_runtime/sel_ldr.c ('k') | src/trusted/service_runtime/sel_load_image.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/trusted/service_runtime/sel_ldr_standard.c
===================================================================
--- src/trusted/service_runtime/sel_ldr_standard.c (revision 1006)
+++ src/trusted/service_runtime/sel_ldr_standard.c (working copy)
@@ -36,7 +36,6 @@
#include "native_client/src/include/portability.h"
#include <stdio.h>
-
#include <stdlib.h>
#include <string.h>
@@ -49,6 +48,7 @@
#include "native_client/src/trusted/service_runtime/include/sys/errno.h"
#include "native_client/src/trusted/service_runtime/arch/sel_ldr_arch.h"
+#include "native_client/src/trusted/service_runtime/elf_util.h"
#include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
#include "native_client/src/trusted/service_runtime/nacl_check.h"
#include "native_client/src/trusted/service_runtime/nacl_closure.h"
@@ -61,286 +61,14 @@
#define PTR_ALIGN_MASK ((sizeof(void *))-1)
-/*
- * Other than empty segments, these are the only ones that are allowed.
- */
-struct NaClPhdrChecks nacl_phdr_check_data[] = {
- /* phdr */
- { PT_PHDR, PF_R, PCA_IGNORE, 0, 0, },
- /* text */
- { PT_LOAD, PF_R|PF_X, PCA_TEXT_CHECK, 1, NACL_TRAMPOLINE_END, },
- /* rodata */
- { PT_LOAD, PF_R, PCA_NONE, 0, 0, },
- /* data/bss */
- { PT_LOAD, PF_R|PF_W, PCA_NONE, 0, 0, },
-#if NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
- /* arm exception handling unwind info (for c++)*/
- /* TODO(robertm): for some reason this does NOT end up in ro maybe because
- * it is relocatable. Try hacking the linker script to move it.
- */
- { PT_ARM_EXIDX, PF_R, PCA_IGNORE, 0, 0, },
-#endif
- /*
- * allow optional GNU stack permission marker, but require that the
- * stack is non-executable.
- */
- { PT_GNU_STACK, PF_R|PF_W, PCA_NONE, 0, 0, },
-};
-
-NaClErrorCode NaClProcessPhdrs(struct NaClApp *nap) {
- /* Scan phdrs and do sanity checks in-line. Verify that the load
- * address is NACL_TRAMPOLINE_END, that we have a single text
- * segment. Data and TLS segments are not required, though it is
- * hard to avoid with standard tools, but in any case there should
- * be at most one each. Ensure that no segment's vaddr is outside
- * of the address space. Ensure that PT_GNU_STACK is present, and
- * that x is off.
- */
- int seen_seg[NACL_ARRAY_SIZE(nacl_phdr_check_data)];
-
- int segnum;
- Elf32_Phdr *php;
- size_t j;
- uintptr_t max_vaddr;
-
- memset(seen_seg, 0, sizeof seen_seg);
- max_vaddr = NACL_TRAMPOLINE_END;
- /*
- * nacl_phdr_check_data is small, so O(|check_data| * nap->elf_hdr.e_phum)
- * is okay.
- */
- for (segnum = 0; segnum < nap->elf_hdr.e_phnum; ++segnum) {
- php = &nap->phdrs[segnum];
- NaClLog(3, "Looking at segment %d, type 0x%x, p_flags 0x%x\n",
- segnum, php->p_type, php->p_flags);
- php->p_flags &= ~PF_MASKOS;
- for (j = 0;
- j < NACL_ARRAY_SIZE(nacl_phdr_check_data);
- ++j) {
- if (php->p_type == nacl_phdr_check_data[j].p_type
- && php->p_flags == nacl_phdr_check_data[j].p_flags) {
- NaClLog(2, "Matched nacl_phdr_check_data[%"PRIdS"]\n", j);
- if (seen_seg[j]) {
- NaClLog(2, "Segment %d is a type that has been seen\n", segnum);
- return LOAD_DUP_SEGMENT;
- }
- ++seen_seg[j];
-
- if (PCA_IGNORE == nacl_phdr_check_data[j].action) {
- NaClLog(3, "Ignoring\n");
- goto next_seg;
- }
-
- if (0 != php->p_memsz) {
- /*
- * We will load this segment later. Do the sanity checks.
- */
- if (0 != nacl_phdr_check_data[j].p_vaddr
- && (nacl_phdr_check_data[j].p_vaddr != php->p_vaddr)) {
- NaClLog(2,
- ("Segment %d: bad virtual address: 0x%08x,"
- " expected 0x%08x\n"),
- segnum,
- php->p_vaddr,
- nacl_phdr_check_data[j].p_vaddr);
- return LOAD_SEGMENT_BAD_LOC;
- }
- if (php->p_vaddr < NACL_TRAMPOLINE_END) {
- NaClLog(2, "Segment %d: virtual address (0x%08x) too low\n",
- segnum,
- php->p_vaddr);
- return LOAD_SEGMENT_OUTSIDE_ADDRSPACE;
- }
- /*
- * integer overflow? Elf32_Addr and Elf32_Word are uint32_t,
- * so the addition/comparison is well defined.
- */
- if (php->p_vaddr + php->p_memsz < php->p_vaddr) {
- NaClLog(2,
- "Segment %d: p_memsz caused integer overflow\n",
- segnum);
- return LOAD_SEGMENT_OUTSIDE_ADDRSPACE;
- }
- if (php->p_vaddr + php->p_memsz >= (1U << nap->addr_bits)) {
- NaClLog(2,
- "Segment %d: too large, ends at 0x%08x\n",
- segnum,
- php->p_vaddr + php->p_memsz);
- return LOAD_SEGMENT_OUTSIDE_ADDRSPACE;
- }
- if (php->p_filesz > php->p_memsz) {
- NaClLog(2,
- ("Segment %d: file size 0x%08x larger"
- " than memory size 0x%08x\n"),
- segnum,
- php->p_filesz,
- php->p_memsz);
- return LOAD_SEGMENT_BAD_PARAM;
- }
-
- php->p_flags |= PF_OS_WILL_LOAD;
- /* record our decision that we will load this segment */
-
- /*
- * NACL_TRAMPOLINE_END <= p_vaddr
- * <= p_vaddr + p_memsz
- * < (1U << nap->addr_bits)
- */
- if (max_vaddr < php->p_vaddr + php->p_memsz) {
- max_vaddr = php->p_vaddr + php->p_memsz;
- }
- }
-
- switch (nacl_phdr_check_data[j].action) {
- case PCA_NONE:
- break;
- case PCA_TEXT_CHECK:
- if (0 == php->p_memsz) {
- return LOAD_BAD_ELF_TEXT;
- }
- nap->text_region_bytes = php->p_filesz;
- break;
- case PCA_IGNORE:
- break;
- }
- goto next_seg;
- }
- }
- /* segment not in nacl_phdr_check_data */
- if (0 == php->p_memsz) {
- NaClLog(3, "Segment %d zero size: ignored\n", segnum);
- continue;
- }
- NaClLog(2,
- "Segment %d is of unexpected type 0x%x, flag 0x%x\n",
- segnum,
- php->p_type,
- php->p_flags);
- return LOAD_BAD_SEGMENT;
- next_seg:
- ;
- }
- for (j = 0;
- j < NACL_ARRAY_SIZE(nacl_phdr_check_data);
- ++j) {
- if (nacl_phdr_check_data[j].required && !seen_seg[j]) {
- return LOAD_REQUIRED_SEG_MISSING;
- }
- }
- nap->data_end = nap->break_addr = max_vaddr;
- /*
- * Memory allocation will use NaClRoundPage(nap->break_addr), but
- * the system notion of break is always an exact address. Even
- * though we must allocate and make accessible multiples of pages,
- * the linux-style brk system call (which returns current break on
- * failure) permits an arbitrarily aligned address as argument.
- */
-
- return LOAD_OK;
-}
-
-
-static void NaClDumpElfHeader(Elf32_Ehdr *elf_hdr) {
-#define DUMP(m,f) do { NaClLog(2, \
- #m " = %" f "\n", \
- elf_hdr->m); } while (0)
- DUMP(e_ident+1, ".3s");
- DUMP(e_type, "#x");
- DUMP(e_machine, "#x");
- DUMP(e_version, "#x");
- DUMP(e_entry, "#x");
- DUMP(e_phoff, "#x");
- DUMP(e_shoff, "#x");
- DUMP(e_flags, "#x");
- DUMP(e_ehsize, "#x");
- DUMP(e_phentsize, "#x");
- DUMP(e_phnum, "#x");
- DUMP(e_shentsize, "#x");
- DUMP(e_shnum, "#x");
- DUMP(e_shstrndx, "#x");
-#undef DUMP
- NaClLog(2, "sizeof(Elf32_Ehdr) = %x\n", (int) sizeof *elf_hdr);
-}
-
-
-static NaClErrorCode NaClValidateElfHeader(Elf32_Ehdr *hdr,
- enum NaClAbiMismatchOption
- abi_mismatch_option) {
- if (memcmp(hdr->e_ident, ELFMAG, SELFMAG)) {
- return LOAD_BAD_ELF_MAGIC;
- }
- if (ELFCLASS32 != hdr->e_ident[EI_CLASS]) {
- return LOAD_NOT_32_BIT;
- }
-
-#if !defined(DANGEROUS_DEBUG_MODE_DISABLE_INNER_SANDBOX)
- if (ELFOSABI_NACL != hdr->e_ident[EI_OSABI]) {
- NaClLog(LOG_ERROR, "Expected OSABI %d, got %d\n",
- ELFOSABI_NACL,
- hdr->e_ident[EI_OSABI]);
- if (abi_mismatch_option == NACL_ABI_MISMATCH_OPTION_ABORT) {
- return LOAD_BAD_ABI;
- }
- }
-
- if (EF_NACL_ABIVERSION != hdr->e_ident[EI_ABIVERSION]) {
- NaClLog(LOG_ERROR, "Expected ABIVERSION %d, got %d\n",
- EF_NACL_ABIVERSION,
- hdr->e_ident[EI_ABIVERSION]);
- if (abi_mismatch_option == NACL_ABI_MISMATCH_OPTION_ABORT) {
- return LOAD_BAD_ABI;
- }
- }
-#else
- UNREFERENCED_PARAMETER(abi_mismatch_option);
-#endif
-
- if (ET_EXEC != hdr->e_type) {
- return LOAD_NOT_EXEC;
- }
-
- if (EM_EXPECTED_BY_NACL != hdr->e_machine) {
- return LOAD_BAD_MACHINE;
- }
-
- if (EV_CURRENT != hdr->e_version) {
- return LOAD_BAD_ELF_VERS;
- }
-
- return LOAD_OK;
-}
-
-
-static void NaClDumpElfProgramHeader(Elf32_Phdr *phdr) {
-#define DUMP(mem) do { \
- NaClLog(2, "%s: %x\n", #mem, phdr->mem); \
- } while (0)
-
- DUMP(p_type);
- DUMP(p_offset);
- DUMP(p_vaddr);
- DUMP(p_paddr);
- DUMP(p_filesz);
- DUMP(p_memsz);
- DUMP(p_flags);
- NaClLog(2, " (%s %s %s)\n",
- (phdr->p_flags & PF_R) ? "PF_R" : "",
- (phdr->p_flags & PF_W) ? "PF_W" : "",
- (phdr->p_flags & PF_X) ? "PF_X" : "");
- DUMP(p_align);
-#undef DUMP
- NaClLog(2, "\n");
-}
-
-
-NaClErrorCode NaClAppLoadFile(struct Gio *gp,
- struct NaClApp *nap,
- enum NaClAbiMismatchOption abi_mismatch_option) {
- NaClErrorCode ret = LOAD_INTERNAL;
- NaClErrorCode subret;
- int cur_ph;
-
+NaClErrorCode NaClAppLoadFile(struct Gio *gp,
+ struct NaClApp *nap,
+ enum NaClAbiCheckOption check_abi) {
+ NaClErrorCode ret = LOAD_INTERNAL;
+ NaClErrorCode subret;
+ uintptr_t max_vaddr;
+ struct NaClElfImage *image = NULL;
/* NACL_MAX_ADDR_BITS < 32 */
if (nap->addr_bits > NACL_MAX_ADDR_BITS) {
ret = LOAD_ADDR_SPACE_TOO_BIG;
@@ -349,89 +77,58 @@
nap->stack_size = NaClRoundAllocPage(nap->stack_size);
- /* nap->addr_bits <= NACL_MAX_ADDR_BITS < 32 */
- if ((*gp->vtbl->Read)(gp,
- &nap->elf_hdr,
- sizeof nap->elf_hdr)
- != sizeof nap->elf_hdr) {
- ret = LOAD_READ_ERROR;
- goto done;
- }
+ /* temporay object will be deleted at end of function */
+ image = NaClElfImageNew(gp);
+#if !defined(DANGEROUS_DEBUG_MODE_DISABLE_INNER_SANDBOX)
+ check_abi = NACL_ABI_CHECK_OPTION_CHECK;
+#endif
- NaClDumpElfHeader(&nap->elf_hdr);
-
- subret = NaClValidateElfHeader(&nap->elf_hdr, abi_mismatch_option);
- if (subret != LOAD_OK) {
- ret = subret;
- goto done;
- }
-
- nap->entry_pt = nap->elf_hdr.e_entry;
-
- if (nap->elf_hdr.e_flags & EF_NACL_ALIGN_MASK) {
- unsigned long eflags = nap->elf_hdr.e_flags & EF_NACL_ALIGN_MASK;
- if (eflags == EF_NACL_ALIGN_16) {
- nap->align_boundary = 16;
- } else if (eflags == EF_NACL_ALIGN_32) {
- nap->align_boundary = 32;
- } else {
- ret = LOAD_BAD_ABI;
+ if (check_abi == NACL_ABI_CHECK_OPTION_CHECK) {
+ subret = NaClElfImageValidateAbi(image);
+ if (subret != LOAD_OK) {
+ ret = subret;
goto done;
}
- } else {
- nap->align_boundary = 32;
+
}
- /* read program headers */
- if (nap->elf_hdr.e_phnum > NACL_MAX_PROGRAM_HEADERS) {
- ret = LOAD_TOO_MANY_SECT; /* overloaded */
+ subret = NaClElfImageValidateElfHeader(image);
+ if (subret != LOAD_OK) {
+ ret = subret;
goto done;
}
- /* TODO(robertm): determine who allocated this */
- free(nap->phdrs);
-
- nap->phdrs = malloc(nap->elf_hdr.e_phnum * sizeof nap->phdrs[0]);
- if (!nap->phdrs) {
- ret = LOAD_NO_MEMORY;
+ subret = NaClElfImageValidateProgramHeaders(image,
+ nap->addr_bits,
+ &nap->text_region_bytes,
+ &max_vaddr);
+ if (subret != LOAD_OK) {
+ ret = subret;
goto done;
}
- if (nap->elf_hdr.e_phentsize < sizeof nap->phdrs[0]) {
- ret = LOAD_BAD_SECT;
- goto done;
- }
- for (cur_ph = 0; cur_ph < nap->elf_hdr.e_phnum; ++cur_ph) {
- if ((*gp->vtbl->Seek)(gp,
- nap->elf_hdr.e_phoff
- + cur_ph * nap->elf_hdr.e_phentsize,
- SEEK_SET) == -1) {
- ret = LOAD_BAD_SECT;
- goto done;
- }
- if ((*gp->vtbl->Read)(gp,
- &nap->phdrs[cur_ph],
- sizeof nap->phdrs[0])
- != sizeof nap->phdrs[0]) {
- ret = LOAD_BAD_SECT;
- goto done;
- }
+ nap->break_addr = max_vaddr;
+ nap->data_end = max_vaddr;
- NaClDumpElfProgramHeader(&nap->phdrs[cur_ph]);
- }
-
- /*
- * We need to determine the size of the CS region. (The DS and SS
- * region sizes are obvious -- the entire application address
- * space.) NaClProcessPhdrs will figure out nap->text_region_bytes.
- */
-
- subret = NaClProcessPhdrs(nap);
- if (subret != LOAD_OK) {
- ret = subret;
+ nap->align_boundary = NaClElfImageGetAlignBoundary(image);
+ if (nap->align_boundary == 0) {
+ ret = LOAD_BAD_ABI;
goto done;
}
+ nap->entry_pt = NaClElfImageGetEntryPoint(image);
+
+ NaClLog(2,
+ "text_region_bytes: %08x "
+ "break_add: %08"PRIxPTR" "
+ "data_end: %08"PRIxPTR" "
+ "entry_pt: %08x "
+ "align_boundary: %08x\n",
+ nap->text_region_bytes,
+ nap->break_addr,
+ nap->data_end,
+ nap->entry_pt,
+ nap->align_boundary);
if (!NaClAddrIsValidEntryPt(nap, nap->entry_pt)) {
ret = LOAD_BAD_ENTRY;
goto done;
@@ -445,12 +142,14 @@
}
NaClLog(2, "Loading into memory\n");
- subret = NaClLoadImage(gp, nap);
+ subret = NaClElfImageLoad(image, gp, nap->addr_bits, nap->mem_start);
if (subret != LOAD_OK) {
ret = subret;
goto done;
}
+ NaClFillEndOfTextRegion(nap);
+
#if !defined(DANGEROUS_DEBUG_MODE_DISABLE_INNER_SANDBOX)
NaClLog(2, "Validating image\n");
subret = NaClValidateImage(nap);
@@ -487,6 +186,7 @@
ret = LOAD_OK;
done:
+ NaClElfImageDelete(image);
return ret;
}
@@ -615,7 +315,7 @@
if (!NaClAppThreadAllocSegCtor(natp,
nap,
1,
- nap->elf_hdr.e_entry,
+ nap->entry_pt,
NaClSysToUser(nap, stack_ptr),
NaClUserToSys(nap, nap->break_addr),
1)) {
« no previous file with comments | « src/trusted/service_runtime/sel_ldr.c ('k') | src/trusted/service_runtime/sel_load_image.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698