diff options
author | mcgrathr@chromium.org <mcgrathr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-01 00:55:05 +0000 |
---|---|---|
committer | mcgrathr@chromium.org <mcgrathr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-01 00:55:05 +0000 |
commit | 867a46429c82870b18e22b082fe5455721539f43 (patch) | |
tree | 66e5b30a3a3b620f6dc8d96ef49dc4a21e34bdb4 /chrome/nacl.gypi | |
parent | 9ad3f0c227121fc3bb55723894cf21254b566de7 (diff) | |
download | chromium_src-867a46429c82870b18e22b082fe5455721539f43.zip chromium_src-867a46429c82870b18e22b082fe5455721539f43.tar.gz chromium_src-867a46429c82870b18e22b082fe5455721539f43.tar.bz2 |
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
R=bradchen@google.com
Review URL: http://codereview.chromium.org/7776034
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@99089 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/nacl.gypi')
-rw-r--r-- | chrome/nacl.gypi | 116 |
1 files changed, 93 insertions, 23 deletions
diff --git a/chrome/nacl.gypi b/chrome/nacl.gypi index abfab38..42c0035 100644 --- a/chrome/nacl.gypi +++ b/chrome/nacl.gypi @@ -183,9 +183,7 @@ ['OS=="linux"', { 'targets': [ { - 'target_name': 'nacl_helper.so', - # 'executable' will be overridden below when we add the -shared - # flag; here it prevents gyp from using the --whole-archive flag + 'target_name': 'nacl_helper', 'type': 'executable', 'include_dirs': [ '..', @@ -194,7 +192,7 @@ 'nacl', ], 'sources': [ - '../chrome/nacl/nacl_helper_linux.cc', + 'nacl/nacl_helper_linux.cc', ], 'conditions': [ ['toolkit_uses_gtk == 1', { @@ -203,36 +201,108 @@ ], }], ], + 'cflags': ['-fPIE'], 'link_settings': { - # NOTE: '-shared' overrides 'executable' above - 'ldflags': ['-shared', - '-Wl,--version-script=chrome/nacl/nacl_helper_exports.txt', - ], + 'ldflags': ['-pie'], }, }, { - 'target_name': 'nacl_helper_bootstrap', + 'target_name': 'nacl_helper_bootstrap_munge_phdr', 'type': 'executable', - 'dependencies': [ - 'nacl_helper.so', + 'toolsets': ['host'], + 'sources': [ + 'nacl/nacl_helper_bootstrap_munge_phdr.c', + ], + 'libraries': [ + '-lelf', + ], + # This is an ugly kludge because gyp doesn't actually treat + # host_arch=x64 target_arch=ia32 as proper cross compilation. + # It still wants to compile the "host" program with -m32 et + # al. Though a program built that way can indeed run on the + # x86-64 host, we cannot reliably build this program on such a + # host because Ubuntu does not provide the full suite of + # x86-32 libraries in packages that can be installed on an + # x86-64 host; in particular, libelf is missing. So here we + # use the hack of eliding all the -m* flags from the + # compilation lines, getting the command close to what they + # would be if gyp were to really build properly for the host. + # TODO(bradnelson): Clean up with proper cross support. + 'conditions': [ + ['host_arch=="x64"', { + 'cflags/': [['exclude', '-m.*']], + 'ldflags/': [['exclude', '-m.*']], + }], + ], + }, + { + 'target_name': 'nacl_helper_bootstrap_raw', + 'type': 'executable', + 'include_dirs': [ + '..', ], 'sources': [ - '../chrome/nacl/nacl_helper_bootstrap_linux.c', + 'nacl/nacl_helper_bootstrap_linux.c', + # We list the linker script here for documentation purposes. + # But even this doesn't make gyp treat it as a dependency, + # so incremental builds won't relink when the script changes. + # TODO(bradnelson): Fix the dependency handling. + 'nacl/nacl_helper_bootstrap_linux.x', + ], + 'cflags': [ + # The tiny standalone bootstrap program is incompatible with + # -fstack-protector, which might be on by default. That switch + # requires using the standard libc startup code, which we do not. + '-fno-stack-protector', + # We don't want to compile it PIC (or its cousin PIE), because + # it goes at an absolute address anyway, and because any kind + # of PIC complicates life for the x86-32 assembly code. We + # append -fno-* flags here instead of using a 'cflags!' stanza + # to remove -f* flags, just in case some system's compiler + # defaults to using PIC for everything. + '-fno-pic', '-fno-PIC', + '-fno-pie', '-fno-PIE', ], - # TODO(bradchen): Delete the -B argument when Gold supports - # -Ttext properly. Until then use ld.bfd. 'link_settings': { - 'ldflags': ['-B', 'tools/ld_bfd', - # Force text segment at 0x10000 (64KB) - # The max-page-size option is needed on x86-64 linux - # where 4K pages are not the default in the BFD linker. - '-Wl,-Ttext-segment,10000,-z,max-page-size=0x1000', - # reference nacl_helper as a shared library - '<(PRODUCT_DIR)/nacl_helper.so', - '-Wl,-rpath,<(SHARED_LIB_DIR)', - ], + 'ldflags': [ + # TODO(bradchen): Delete the -B argument when Gold is verified + # to produce good results with our custom linker script. + # Until then use ld.bfd. + '-B', 'tools/ld_bfd', + # This programs is (almost) entirely standalone. It has + # its own startup code, so no crt1.o for it. It is + # statically linked, and on x86 it actually does not use + # libc at all. However, on ARM it needs a few (safe) + # things from libc, so we don't use '-nostdlib' here. + '-static', '-nostartfiles', + # Link with our custom linker script to get out special layout. + # TODO(bradnelson): Use some <(foo) instead of chrome/ here. + '-Wl,--script=chrome/nacl/nacl_helper_bootstrap_linux.x', + # On x86-64, the default page size with some + # linkers is 2M rather than the real Linux page + # size of 4K. A larger page size is incompatible + # with our custom linker script's special layout. + '-Wl,-z,max-page-size=0x1000', + ], }, }, + { + 'target_name': 'nacl_helper_bootstrap', + 'dependencies': [ + 'nacl_helper_bootstrap_raw', + 'nacl_helper_bootstrap_munge_phdr#host', + ], + 'type': 'none', + 'actions': [{ + 'action_name': 'munge_phdr', + 'inputs': ['nacl/nacl_helper_bootstrap_munge_phdr.py', + '<(PRODUCT_DIR)/nacl_helper_bootstrap_munge_phdr', + '<(PRODUCT_DIR)/nacl_helper_bootstrap_raw'], + 'outputs': ['<(PRODUCT_DIR)/nacl_helper_bootstrap'], + 'message': 'Munging ELF program header', + 'action': ['python', '<@(_inputs)', '<@(_outputs)'] + }], + } ], }], ], |