diff options
author | jar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-31 01:46:38 +0000 |
---|---|---|
committer | jar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-31 01:46:38 +0000 |
commit | 4451feeb191113651cb1a82862d2bece91290b8d (patch) | |
tree | bac56ba575c66e240b9cd2c0959a7f25d902b1a9 /chrome/nacl/nacl_helper_bootstrap_munge_phdr.c | |
parent | 12274721df2f935cc1147964492ab87edbb3acee (diff) | |
download | chromium_src-4451feeb191113651cb1a82862d2bece91290b8d.zip chromium_src-4451feeb191113651cb1a82862d2bece91290b8d.tar.gz chromium_src-4451feeb191113651cb1a82862d2bece91290b8d.tar.bz2 |
Revert 98909 - Use chain-loading for Linux nacl_helper
This replaces the nacl_helper_bootstrap program, dynamically-linked against
nacl_helper.so, with a standalone, statically-linked nacl_helper_bootstrap
program that loads the dynamic linker, instructing it in turn to load the
nacl_helper program (now a PIE rather than a DSO).
This avoids two problems with the old scheme:
1. The nacl_helper_bootstrap program remained in the dynamic linker's
list of loaded objects, as the main executable, even though the
memory where its .dynamic section had been was overwritten with
the NaCl untrusted address space. Code that traverses the list of
all loaded objects could thus attempt to look at pointers into this
part of memory, and be led astray.
2. nacl_helper_bootstrap's large (~1G) bss segment could cause the kernel
to refuse to load the program because it didn't think there was enough
free memory in the system for so large an allocation of anonymous memory.
The bootstrap program is kept very small by avoiding all use of libc
(except for memset and integer division routines needed on ARM). It has
its own custom start-up code hand-written in assembly and its own custom
system call stubs done with hand-written GCC inline asm statements.
To avoid the second problem, the bootstrap program no longer has a large
bss. Instead, it has a special ELF segment (i.e. PT_LOAD header) that
specifies no memory access, and a large (~1G) mapping size from the file.
This mapping is way off the end of the file, but the kernel doesn't mind
that, and since it's all a file mapping, the kernel does not do its normal
memory accounting for consuming a large amount of anonymous memory.
Unfortunately, it's impossible to get the linker to produce exactly the
right PT_LOAD header by itself. Using a custom linker script, we get the
layout exactly how we want it and a PT_LOAD header that is almost right.
We then use a build-time helper program to munge one field of the PT_LOAD
to make it exactly what we need.
BUG= http://code.google.com/p/chromium/issues/detail?id=94147
TEST= hand-tested chromium build, invoked with --nacl-linux-helper
R=bradchen@google.com,mseaborn@chromium.org
Review URL: http://codereview.chromium.org/7795010
TBR=mcgrathr@chromium.org
Review URL: http://codereview.chromium.org/7811013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98910 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/nacl/nacl_helper_bootstrap_munge_phdr.c')
-rw-r--r-- | chrome/nacl/nacl_helper_bootstrap_munge_phdr.c | 66 |
1 files changed, 0 insertions, 66 deletions
diff --git a/chrome/nacl/nacl_helper_bootstrap_munge_phdr.c b/chrome/nacl/nacl_helper_bootstrap_munge_phdr.c deleted file mode 100644 index 87fe73f..0000000 --- a/chrome/nacl/nacl_helper_bootstrap_munge_phdr.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (c) 2011 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * This is a trivial program to edit an ELF file in place, making - * one crucial modification to a program header. It's invoked: - * bootstrap_phdr_hacker FILENAME SEGMENT_NUMBER - * where SEGMENT_NUMBER is the zero-origin index of the program header - * we'll touch. This is a PT_LOAD with p_filesz of zero. We change its - * p_filesz to match its p_memsz value. - */ - -#include <errno.h> -#include <error.h> -#include <fcntl.h> -#include <gelf.h> -#include <libelf.h> -#include <stdlib.h> -#include <unistd.h> - -int main(int argc, char **argv) { - if (argc != 3) - error(1, 0, "Usage: %s FILENAME SEGMENT_NUMBER", argv[0]); - - const char *const file = argv[1]; - const int segment = atoi(argv[2]); - - int fd = open(file, O_RDWR); - if (fd < 0) - error(2, errno, "Cannot open %s for read/write", file); - - if (elf_version(EV_CURRENT) == EV_NONE) - error(2, 0, "elf_version: %s", elf_errmsg(-1)); - - Elf *elf = elf_begin(fd, ELF_C_RDWR, NULL); - if (elf == NULL) - error(2, 0, "elf_begin: %s", elf_errmsg(-1)); - - if (elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT) == 0) - error(2, 0, "elf_flagelf: %s", elf_errmsg(-1)); - - GElf_Phdr phdr; - GElf_Phdr *ph = gelf_getphdr(elf, segment, &phdr); - if (ph == NULL) - error(2, 0, "gelf_getphdr: %s", elf_errmsg(-1)); - - if (ph->p_type != PT_LOAD) - error(3, 0, "Program header %d is %u, not PT_LOAD", - segment, (unsigned int) ph->p_type); - if (ph->p_filesz != 0) - error(3, 0, "Program header %d has nonzero p_filesz", segment); - - ph->p_filesz = ph->p_memsz; - if (gelf_update_phdr(elf, segment, ph) == 0) - error(2, 0, "gelf_update_phdr: %s", elf_errmsg(-1)); - - if (elf_flagphdr(elf, ELF_C_SET, ELF_F_DIRTY) == 0) - error(2, 0, "elf_flagphdr: %s", elf_errmsg(-1)); - - if (elf_update(elf, ELF_C_WRITE) < 0) - error(2, 0, "elf_update: %s", elf_errmsg(-1)); - - close(fd); - - return 0; -} |