diff options
-rw-r--r-- | chrome/common/chrome_paths.cc | 13 | ||||
-rw-r--r-- | chrome/common/chrome_paths.h | 6 | ||||
-rw-r--r-- | chrome/nacl.gypi | 35 | ||||
-rw-r--r-- | chrome/nacl/nacl_fork_delegate_linux.cc | 22 | ||||
-rw-r--r-- | chrome/nacl/nacl_helper_bootstrap_linux.c | 24 | ||||
-rw-r--r-- | chrome/nacl/nacl_helper_exports.txt | 10 | ||||
-rw-r--r-- | chrome/nacl/nacl_helper_linux.cc | 24 | ||||
-rwxr-xr-x | tools/ld_bfd/ld | 2 |
8 files changed, 124 insertions, 12 deletions
diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc index 550b18b..0758f1e 100644 --- a/chrome/common/chrome_paths.cc +++ b/chrome/common/chrome_paths.cc @@ -52,6 +52,12 @@ const FilePath::CharType kInternalNaClPluginFileName[] = FILE_PATH_LITERAL("libppGoogleNaClPluginChrome.so"); #endif +#if defined(OS_POSIX) && !defined(OS_MACOSX) +// File name of the nacl_helper, Linux only. +const FilePath::CharType kInternalNaClHelperFileName[] = + FILE_PATH_LITERAL("nacl_helper_bootstrap"); +#endif + } // namespace namespace chrome { @@ -234,6 +240,13 @@ bool PathProvider(int key, FilePath* result) { return false; cur = cur.Append(kInternalNaClPluginFileName); break; +#if defined(OS_POSIX) && !defined(OS_MACOSX) + case chrome::FILE_NACL_HELPER: + if (!PathService::Get(base::DIR_MODULE, &cur)) + return false; + cur = cur.Append(kInternalNaClHelperFileName); + break; +#endif case chrome::FILE_RESOURCES_PACK: #if defined(OS_MACOSX) if (base::mac::AmIBundled()) { diff --git a/chrome/common/chrome_paths.h b/chrome/common/chrome_paths.h index 43140ea..4998213 100644 --- a/chrome/common/chrome_paths.h +++ b/chrome/common/chrome_paths.h @@ -40,7 +40,7 @@ enum { // using it. DIR_INTERNAL_PLUGINS, // Directory where internal plugins reside. DIR_MEDIA_LIBS, // Directory where the Media libraries reside. -#if !defined(OS_MACOSX) && defined(OS_POSIX) +#if defined(OS_POSIX) && !defined(OS_MACOSX) DIR_POLICY_FILES, // Directory for system-wide read-only // policy files that allow sys-admins // to set policies for chrome. This directory @@ -68,6 +68,10 @@ enum { FILE_FLASH_PLUGIN, // Full path to the internal Flash plugin file. FILE_PEPPER_FLASH_PLUGIN, // Full path to the pepper Flash plugin file. FILE_PDF_PLUGIN, // Full path to the internal PDF plugin file. + +#if defined(OS_POSIX) && !defined(OS_MACOSX) + FILE_NACL_HELPER, // Full path to Linux nacl_helper executable. +#endif FILE_NACL_PLUGIN, // Full path to the internal NaCl plugin file. FILE_LIBAVCODEC, // Full path to libavcodec media decoding // library. diff --git a/chrome/nacl.gypi b/chrome/nacl.gypi index 9467359..bfc6652 100644 --- a/chrome/nacl.gypi +++ b/chrome/nacl.gypi @@ -144,10 +144,12 @@ }, ], }], - ['OS=="linux" and touchui == 0', { + ['OS=="linux"', { 'targets': [ { - 'target_name': 'nacl_helper', + '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 'type': 'executable', 'include_dirs': [ '..', @@ -165,6 +167,35 @@ ], }], ], + 'link_settings': { + # NOTE: '-shared' overrides 'executable' above + 'ldflags': ['-shared', + '-Wl,--version-script=chrome/nacl/nacl_helper_exports.txt', + ], + }, + }, + { + 'target_name': 'nacl_helper_bootstrap', + 'type': 'executable', + 'dependencies': [ + 'nacl_helper.so', + ], + 'sources': [ + '../chrome/nacl/nacl_helper_bootstrap_linux.c', + ], + # 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)', + ], + }, }, ], }], diff --git a/chrome/nacl/nacl_fork_delegate_linux.cc b/chrome/nacl/nacl_fork_delegate_linux.cc index 794cfda..e5ee01a 100644 --- a/chrome/nacl/nacl_fork_delegate_linux.cc +++ b/chrome/nacl/nacl_fork_delegate_linux.cc @@ -13,9 +13,11 @@ #include "base/eintr_wrapper.h" #include "base/logging.h" #include "base/file_path.h" +#include "base/path_service.h" #include "base/process_util.h" #include "content/common/unix_domain_socket_posix.h" #include "content/common/zygote_fork_delegate_linux.h" +#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/nacl_helper_linux.h" @@ -40,18 +42,24 @@ void NaClForkDelegate::Init(const bool sandboxed, base::file_handle_mapping_vector fds_to_map; fds_to_map.push_back(std::make_pair(fds[1], kNaClZygoteDescriptor)); fds_to_map.push_back(std::make_pair(sandboxdesc, kNaClSandboxDescriptor)); - // TODO(bradchen): Before making this the default for release builds, - // replace command line switch with PathService::Get(). - const std::string nacl_zygote_exe = - CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kNaClLinuxHelper); + // TODO(bradchen): To make this the default for release builds, + // remove command line switch. ready_ = false; - if (nacl_zygote_exe.length() != 0) { + const bool use_helper = CommandLine::ForCurrentProcess()->HasSwitch( + switches::kNaClLinuxHelper); + FilePath helper_exe; + if (use_helper && PathService::Get(chrome::FILE_NACL_HELPER, &helper_exe)) { CommandLine::StringVector argv = CommandLine::ForCurrentProcess()->argv(); - argv[0] = nacl_zygote_exe; + argv[0] = helper_exe.value(); base::LaunchOptions options; options.fds_to_remap = &fds_to_map; options.clone_flags = CLONE_FS | SIGCHLD; + // LD_BIND_NOW forces non-lazy binding in the dynamic linker, to + // prevent the linker from trying to look at the text of the nacl_helper + // program after it has been replaced by the nacl module. + base::environment_vector env; + env.push_back(std::make_pair("LD_BIND_NOW", "1")); + options.environ = &env; ready_ = base::LaunchProcess(argv, options, NULL); // parent and error cases are handled below } diff --git a/chrome/nacl/nacl_helper_bootstrap_linux.c b/chrome/nacl/nacl_helper_bootstrap_linux.c new file mode 100644 index 0000000..7a0ace7 --- /dev/null +++ b/chrome/nacl/nacl_helper_bootstrap_linux.c @@ -0,0 +1,24 @@ +/* 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. + * + * Bootstraping the nacl_helper. This executable reserves the bottom 1G + * of the address space, then invokes nacl_helper_init. Note that, + * as the text of this executable will eventually be overwritten by the + * native_client module, nacl_helper_init must not attempt to return. + */ + +#include <stdlib.h> + +/* reserve 1GB of space */ +#define ONEGIG (1 << 30) +char nacl_reserved_space[ONEGIG]; + +void nacl_helper_init(int argc, char *argv[], + const char *nacl_reserved_space); + +int main(int argc, char *argv[]) { + nacl_helper_init(argc, argv, nacl_reserved_space); + abort(); + return 0; // convince the tools I'm sane. +} diff --git a/chrome/nacl/nacl_helper_exports.txt b/chrome/nacl/nacl_helper_exports.txt new file mode 100644 index 0000000..af930c1 --- /dev/null +++ b/chrome/nacl/nacl_helper_exports.txt @@ -0,0 +1,10 @@ +# gnu-ld version script for exporting desired symbols from nacl_helper +# + +NACL_HELPER_1_0 { + global: + nacl_helper_init; + nacl_helper_get_1G_address; + local: + *; +}; diff --git a/chrome/nacl/nacl_helper_linux.cc b/chrome/nacl/nacl_helper_linux.cc index b943e2b..b53cf8d 100644 --- a/chrome/nacl/nacl_helper_linux.cc +++ b/chrome/nacl/nacl_helper_linux.cc @@ -116,14 +116,33 @@ void HandleForkRequest(const std::vector<int>& child_fds) { } // namespace -int main(int argc, char *argv[]) { +static const void* g_nacl_reserved_space = NULL; +extern "C" __attribute__((visibility("default"))) +const void* nacl_helper_get_1G_address() { + return g_nacl_reserved_space; +} + +// nacl_helper_init does the real work of this module. It is invoked as +// a static constructor and never returns, preventing main() from the +// nacl_helper_bootstrap program from being called. +// +// NOTE This routine must not return. +extern "C" __attribute__((visibility("default"))) +void nacl_helper_init(int argc, char *argv[], + const char *nacl_reserved_space) { CommandLine::Init(argc, argv); base::AtExitManager exit_manager; base::RandUint64(); // acquire /dev/urandom fd before sandbox is raised std::vector<int> empty; // for SendMsg() calls g_suid_sandbox_active = (NULL != getenv("SBX_D")); - + g_nacl_reserved_space = nacl_reserved_space; + if (!nacl_reserved_space) { + VLOG(1) << "nacl_reserved_space is NULL"; + } else { + VLOG(1) << "nacl_reserved_space is at " + << (void *)nacl_reserved_space; + } // Send the zygote a message to let it know we are ready to help if (!UnixDomainSocket::SendMsg(kNaClZygoteDescriptor, kNaClHelperStartupAck, @@ -163,4 +182,5 @@ int main(int argc, char *argv[]) { LOG(ERROR) << "*** send() to zygote failed"; } } + CHECK(false); // This routine must not return } diff --git a/tools/ld_bfd/ld b/tools/ld_bfd/ld index 5a5d84e..124f202 100755 --- a/tools/ld_bfd/ld +++ b/tools/ld_bfd/ld @@ -34,6 +34,8 @@ def main(): continue if arg == "-Wl,--thread-count=4" or arg == "--thread-count=4": continue + if arg == "--icf=none": + continue args.append(arg) print("ld_bfd/ld: exec ", args) sys.exit(subprocess.call(args)) |