diff options
-rw-r--r-- | components/nacl.gyp | 5 | ||||
-rw-r--r-- | components/nacl/loader/DEPS | 3 | ||||
-rw-r--r-- | components/nacl/loader/nacl_listener.cc | 52 | ||||
-rw-r--r-- | components/nacl/loader/nonsfi/DEPS | 3 | ||||
-rw-r--r-- | components/nacl/loader/nonsfi/irt_interfaces.cc | 1 | ||||
-rw-r--r-- | components/nacl/loader/nonsfi/irt_interfaces.h | 1 | ||||
-rw-r--r-- | components/nacl/loader/nonsfi/irt_ppapi.cc | 44 | ||||
-rw-r--r-- | components/nacl/loader/nonsfi/nonsfi_main.cc | 61 | ||||
-rw-r--r-- | ipc/ipc_channel.h | 6 | ||||
-rw-r--r-- | ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h | 3 | ||||
-rw-r--r-- | ppapi/ppapi_proxy.gypi | 3 | ||||
-rw-r--r-- | ppapi/proxy/irt_ppapi.c | 2 | ||||
-rw-r--r-- | ppapi/proxy/plugin_main_irt.cc (renamed from ppapi/proxy/plugin_main_nacl.cc) | 57 | ||||
-rw-r--r-- | ppapi/proxy/plugin_main_irt.h | 31 |
14 files changed, 233 insertions, 39 deletions
diff --git a/components/nacl.gyp b/components/nacl.gyp index 8f0ff77f..3f67983 100644 --- a/components/nacl.gyp +++ b/components/nacl.gyp @@ -181,9 +181,11 @@ 'dependencies': [ 'nacl', 'nacl_common', + '../components/tracing.gyp:tracing', '../crypto/crypto.gyp:crypto', '../sandbox/sandbox.gyp:libc_urandom_override', '../sandbox/sandbox.gyp:sandbox', + '../ppapi/ppapi_internal.gyp:ppapi_proxy', ], 'defines': [ '<@(nacl_defines)', @@ -206,6 +208,7 @@ 'nacl/loader/nonsfi/irt_interfaces.cc', 'nacl/loader/nonsfi/irt_interfaces.h', 'nacl/loader/nonsfi/irt_memory.cc', + 'nacl/loader/nonsfi/irt_ppapi.cc', 'nacl/loader/nonsfi/irt_thread.cc', 'nacl/loader/nonsfi/irt_util.h', 'nacl/loader/nonsfi/nonsfi_main.cc', @@ -216,6 +219,8 @@ '../content/common/sandbox_linux/sandbox_init_linux.cc', '../content/common/sandbox_linux/sandbox_seccomp_bpf_linux.cc', '../content/public/common/content_switches.cc', + '../ppapi/proxy/plugin_main_irt.cc', + '../ppapi/proxy/plugin_main_irt.h', ], 'conditions': [ ['toolkit_uses_gtk == 1', { diff --git a/components/nacl/loader/DEPS b/components/nacl/loader/DEPS index 8345fef..6167777 100644 --- a/components/nacl/loader/DEPS +++ b/components/nacl/loader/DEPS @@ -22,6 +22,9 @@ include_rules = [ "+ppapi/proxy/nacl_message_scanner.h", "+ppapi/proxy/serialized_handle.h", + # For setting FDs in non-SFI mode. + "+ppapi/proxy/plugin_main_irt.h", + # For sending PpapiHostMsg_ChannelCreated in nacl_ipc_adapter.cc: "+ppapi/proxy/ppapi_messages.h" ] diff --git a/components/nacl/loader/nacl_listener.cc b/components/nacl/loader/nacl_listener.cc index c35d946..4bafc8c 100644 --- a/components/nacl/loader/nacl_listener.cc +++ b/components/nacl/loader/nacl_listener.cc @@ -35,6 +35,7 @@ #if defined(OS_LINUX) #include "components/nacl/loader/nonsfi/nonsfi_main.h" #include "content/public/common/child_process_sandbox_support_linux.h" +#include "ppapi/proxy/plugin_main_irt.h" #endif #if defined(OS_WIN) @@ -279,19 +280,54 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) { } if (params.enable_ipc_proxy) { - // Create the PPAPI IPC channels between the NaCl IRT and the hosts - // (browser/renderer) processes. The IRT uses these channels to communicate - // with the host and to initialize the IPC dispatchers. IPC::ChannelHandle browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); - SetUpIPCAdapter(&browser_handle, io_thread_.message_loop_proxy(), - nap, NACL_CHROME_DESC_BASE); - IPC::ChannelHandle renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); - SetUpIPCAdapter(&renderer_handle, io_thread_.message_loop_proxy(), - nap, NACL_CHROME_DESC_BASE + 1); +#if defined(OS_LINUX) + if (params.enable_nonsfi_mode) { + // In non-SFI mode, we neither intercept nor rewrite the message using + // NaClIPCAdapter, and the channels are connected between the plugin and + // the hosts directly. So, the IPC::Channel instances will be created in + // the plugin side, because the IPC::Listener needs to live on the + // plugin's main thread. However, on initialization (i.e. before loading + // the plugin binary), the FD needs to be passed to the hosts. So, here + // we create raw FD pairs, and pass the client side FDs to the hosts, + // and the server side FDs to the plugin. + int browser_server_ppapi_fd; + int browser_client_ppapi_fd; + int renderer_server_ppapi_fd; + int renderer_client_ppapi_fd; + if (!IPC::SocketPair( + &browser_server_ppapi_fd, &browser_client_ppapi_fd) || + !IPC::SocketPair( + &renderer_server_ppapi_fd, &renderer_client_ppapi_fd)) { + LOG(ERROR) << "Failed to create sockets for IPC."; + return; + } + + // Set the plugin IPC channel FDs. + SetIPCFileDescriptors( + browser_server_ppapi_fd, renderer_server_ppapi_fd); + + // Send back to the client side IPC channel FD to the host. + browser_handle.socket = + base::FileDescriptor(browser_client_ppapi_fd, true); + renderer_handle.socket = + base::FileDescriptor(renderer_client_ppapi_fd, true); + } else { +#endif + // Create the PPAPI IPC channels between the NaCl IRT and the host + // (browser/renderer) processes. The IRT uses these channels to + // communicate with the host and to initialize the IPC dispatchers. + SetUpIPCAdapter(&browser_handle, io_thread_.message_loop_proxy(), + nap, NACL_CHROME_DESC_BASE); + SetUpIPCAdapter(&renderer_handle, io_thread_.message_loop_proxy(), + nap, NACL_CHROME_DESC_BASE + 1); +#if defined(OS_LINUX) + } +#endif if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( browser_handle, renderer_handle))) LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; diff --git a/components/nacl/loader/nonsfi/DEPS b/components/nacl/loader/nonsfi/DEPS new file mode 100644 index 0000000..fa6de5d --- /dev/null +++ b/components/nacl/loader/nonsfi/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+ppapi/nacl_irt", +] diff --git a/components/nacl/loader/nonsfi/irt_interfaces.cc b/components/nacl/loader/nonsfi/irt_interfaces.cc index c53c795..4364bb8 100644 --- a/components/nacl/loader/nonsfi/irt_interfaces.cc +++ b/components/nacl/loader/nonsfi/irt_interfaces.cc @@ -29,6 +29,7 @@ const NaClInterfaceTable kIrtInterfaces[] = { NACL_INTERFACE_TABLE(NACL_IRT_FUTEX_v0_1, kIrtFutex), NACL_INTERFACE_TABLE(NACL_IRT_TLS_v0_1, kIrtTls), NACL_INTERFACE_TABLE(NACL_IRT_CLOCK_v0_1, kIrtClock), + NACL_INTERFACE_TABLE(NACL_IRT_PPAPIHOOK_v0_1, kIrtPpapiHook), }; #undef NACL_INTERFACE_TABLE diff --git a/components/nacl/loader/nonsfi/irt_interfaces.h b/components/nacl/loader/nonsfi/irt_interfaces.h index 78c5bf0..a2bf468 100644 --- a/components/nacl/loader/nonsfi/irt_interfaces.h +++ b/components/nacl/loader/nonsfi/irt_interfaces.h @@ -21,6 +21,7 @@ extern const struct nacl_irt_thread kIrtThread; extern const struct nacl_irt_futex kIrtFutex; extern const struct nacl_irt_tls kIrtTls; extern const struct nacl_irt_clock kIrtClock; +extern const struct nacl_irt_ppapihook kIrtPpapiHook; } // namespace nonsfi } // namespace nacl diff --git a/components/nacl/loader/nonsfi/irt_ppapi.cc b/components/nacl/loader/nonsfi/irt_ppapi.cc new file mode 100644 index 0000000..ebe2893 --- /dev/null +++ b/components/nacl/loader/nonsfi/irt_ppapi.cc @@ -0,0 +1,44 @@ +// Copyright 2014 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. + +#include "base/logging.h" +#include "components/nacl/loader/nonsfi/irt_interfaces.h" +#include "ppapi/c/ppp.h" +#include "ppapi/nacl_irt/irt_ppapi.h" +#include "ppapi/proxy/plugin_main_irt.h" + +namespace nacl { +namespace nonsfi { +namespace { + +struct PP_StartFunctions g_pp_functions; + +int IrtPpapiStart(const struct PP_StartFunctions* funcs) { + g_pp_functions = *funcs; + return PpapiPluginMain(); +} + +} // namespace + +const struct nacl_irt_ppapihook kIrtPpapiHook = { + IrtPpapiStart, + PpapiPluginRegisterThreadCreator, +}; + +} // namespace nonsfi +} // namespace nacl + +int32_t PPP_InitializeModule(PP_Module module_id, + PPB_GetInterface get_browser_interface) { + return nacl::nonsfi::g_pp_functions.PPP_InitializeModule( + module_id, get_browser_interface); +} + +void PPP_ShutdownModule(void) { + nacl::nonsfi::g_pp_functions.PPP_ShutdownModule(); +} + +const void *PPP_GetInterface(const char *interface_name) { + return nacl::nonsfi::g_pp_functions.PPP_GetInterface(interface_name); +} diff --git a/components/nacl/loader/nonsfi/nonsfi_main.cc b/components/nacl/loader/nonsfi/nonsfi_main.cc index d9847c52..87fbc1b 100644 --- a/components/nacl/loader/nonsfi/nonsfi_main.cc +++ b/components/nacl/loader/nonsfi/nonsfi_main.cc @@ -4,8 +4,10 @@ #include "components/nacl/loader/nonsfi/nonsfi_main.h" +#include "base/debug/leak_annotations.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "base/threading/platform_thread.h" #include "components/nacl/loader/nonsfi/elf_loader.h" #include "components/nacl/loader/nonsfi/irt_interfaces.h" #include "native_client/src/include/elf_auxv.h" @@ -22,6 +24,41 @@ namespace nacl { namespace nonsfi { namespace { +typedef void (*EntryPointType)(uintptr_t*); + +class PluginMainDelegate : public base::PlatformThread::Delegate { + public: + explicit PluginMainDelegate(EntryPointType entry_point) + : entry_point_(entry_point) { + } + + virtual ~PluginMainDelegate() { + } + + virtual void ThreadMain() OVERRIDE { + base::PlatformThread::SetName("NaClMainThread"); + + uintptr_t info[] = { + 0, // Do not use fini. + 0, // envc. + 0, // argc. + 0, // Null terminate for argv. + 0, // Null terminate for envv. + AT_SYSINFO, + reinterpret_cast<uintptr_t>(&NaClIrtInterface), + AT_NULL, + 0, // Null terminate for auxv. + }; + entry_point_(info); + } + + private: + EntryPointType entry_point_; +}; + +// Default stack size of the plugin main thread. We heuristically chose 16M. +const size_t kStackSize = (16 << 20); + struct NaClDescUnrefer { void operator()(struct NaClDesc* desc) const { NaClDescUnref(desc); @@ -46,22 +83,16 @@ void LoadModuleRpc(struct NaClSrpcRpc* rpc, return; } - uintptr_t entry_point = image.entry_point(); - rpc->result = NACL_SRPC_RESULT_OK; + EntryPointType entry_point = + reinterpret_cast<EntryPointType>(image.entry_point()); + if (!base::PlatformThread::CreateNonJoinable( + kStackSize, new PluginMainDelegate(entry_point))) { + LOG(ERROR) << "LoadModuleRpc: Failed to create plugin main thread."; + return; + } - // Run for testing. TODO(hidehiko): Remove this. - uintptr_t info[] = { - 0, // Do not use fini. - 0, // envc. - 0, // argc. - 0, // Null terminate for argv. - 0, // Null terminate for envv. - AT_SYSINFO, - reinterpret_cast<uintptr_t>(&NaClIrtInterface), - AT_NULL, - 0, // Null terminate for auxv. - }; - reinterpret_cast<void (*)(uintptr_t*)>(entry_point)(info); + rpc->result = NACL_SRPC_RESULT_OK; + (*done_cls->Run)(done_cls); } const static struct NaClSrpcHandlerDesc kNonSfiServiceHandlers[] = { diff --git a/ipc/ipc_channel.h b/ipc/ipc_channel.h index 7e09a80..bfa5ec6 100644 --- a/ipc/ipc_channel.h +++ b/ipc/ipc_channel.h @@ -217,6 +217,12 @@ class IPC_EXPORT Channel : public Sender { ChannelImpl *channel_impl_; }; +#if defined(OS_POSIX) +// SocketPair() creates a pair of socket FDs suitable for using with +// IPC::Channel. +IPC_EXPORT bool SocketPair(int* fd1, int* fd2); +#endif + } // namespace IPC #endif // IPC_IPC_CHANNEL_H_ diff --git a/ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h b/ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h index c7fe8a0..ac23a34 100644 --- a/ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h +++ b/ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h @@ -15,9 +15,6 @@ EXTERN_C_BEGIN // The entry point for the main thread of the PPAPI plugin process. int PpapiPluginMain(void); -void PpapiPluginRegisterThreadCreator( - const struct PP_ThreadFunctions* new_funcs); - EXTERN_C_END #endif // NATIVE_CLIENT_SRC_SHARED_PPAPI_PROXY_PPRUNTIME_H_ diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi index f345414..d6fc604 100644 --- a/ppapi/ppapi_proxy.gypi +++ b/ppapi/ppapi_proxy.gypi @@ -112,7 +112,6 @@ 'proxy/plugin_dispatcher.h', 'proxy/plugin_globals.cc', 'proxy/plugin_globals.h', - 'proxy/plugin_main_nacl.cc', 'proxy/plugin_message_filter.cc', 'proxy/plugin_message_filter.h', 'proxy/plugin_resource.cc', @@ -244,6 +243,8 @@ ['>(nacl_untrusted_build)==1', { 'sources': [ 'proxy/irt_ppapi.c', + 'proxy/plugin_main_irt.cc', + 'proxy/plugin_main_irt.h', ], 'sources!': [ 'proxy/audio_input_resource.cc', diff --git a/ppapi/proxy/irt_ppapi.c b/ppapi/proxy/irt_ppapi.c index be6a216..24dafdb 100644 --- a/ppapi/proxy/irt_ppapi.c +++ b/ppapi/proxy/irt_ppapi.c @@ -8,7 +8,7 @@ #include "native_client/src/untrusted/irt/irt.h" #include "native_client/src/untrusted/irt/irt_private.h" #include "ppapi/nacl_irt/irt_ppapi.h" -#include "ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h" +#include "ppapi/proxy/plugin_main_irt.h" struct PP_StartFunctions g_pp_functions; diff --git a/ppapi/proxy/plugin_main_nacl.cc b/ppapi/proxy/plugin_main_irt.cc index c84828d..a3ea6c1 100644 --- a/ppapi/proxy/plugin_main_nacl.cc +++ b/ppapi/proxy/plugin_main_irt.cc @@ -1,9 +1,10 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 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. -#include <unistd.h> +#include "ppapi/proxy/plugin_main_irt.h" +#include <unistd.h> #include <map> #include <set> @@ -13,6 +14,7 @@ // IPC_MESSAGE_MACROS_LOG_ENABLED so ppapi_messages.h will generate the // ViewMsgLog et al. functions. +#include "base/at_exit.h" #include "base/command_line.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" @@ -23,11 +25,8 @@ #include "ipc/ipc_channel_handle.h" #include "ipc/ipc_logging.h" #include "ipc/ipc_message.h" -#include "native_client/src/public/chrome_main.h" -#include "native_client/src/shared/srpc/nacl_srpc.h" #include "ppapi/c/ppp.h" #include "ppapi/c/ppp_instance.h" -#include "ppapi/native_client/src/shared/ppapi_proxy/ppruntime.h" #include "ppapi/proxy/plugin_dispatcher.h" #include "ppapi/proxy/plugin_globals.h" #include "ppapi/proxy/plugin_message_filter.h" @@ -36,6 +35,11 @@ #include "ppapi/shared_impl/ppapi_switches.h" #include "ppapi/shared_impl/ppb_audio_shared.h" +#if defined(__native_client__) +#include "native_client/src/public/chrome_main.h" +#include "native_client/src/shared/srpc/nacl_srpc.h" +#endif + #if defined(IPC_MESSAGE_LOG_ENABLED) #include "base/containers/hash_tables.h" @@ -56,6 +60,19 @@ using ppapi::proxy::SerializedHandle; namespace { +#if defined(__native_client__) +// In SFI mode, the FDs of IPC channels are NACL_CHROME_DESC_BASE and its +// successor, which is set in nacl_listener.cc. +int g_nacl_ipc_browser_fd = NACL_CHROME_DESC_BASE; +int g_nacl_ipc_renderer_fd = NACL_CHROME_DESC_BASE + 1; +#else +// In non-SFI mode, the FDs of IPC channels are different from the hard coded +// ones. These values will be set by SetIPCFileDescriptors() below. +// At first, both are initialized to invalid FD number (-1). +int g_nacl_ipc_browser_fd = -1; +int g_nacl_ipc_renderer_fd = -1; +#endif + // This class manages communication between the plugin and the browser, and // manages the PluginDispatcher instances for communication between the plugin // and the renderer. @@ -113,10 +130,10 @@ PpapiDispatcher::PpapiDispatcher(scoped_refptr<base::MessageLoopProxy> io_loop) : next_plugin_dispatcher_id_(0), message_loop_(io_loop), shutdown_event_(true, false) { - // The first FD (based on NACL_CHROME_DESC_BASE) is the IPC channel to the - // browser. + DCHECK_NE(g_nacl_ipc_browser_fd, -1) + << "g_nacl_ipc_browser_fd must be initialized before the plugin starts"; IPC::ChannelHandle channel_handle( - "NaCl IPC", base::FileDescriptor(NACL_CHROME_DESC_BASE, false)); + "NaCl IPC", base::FileDescriptor(g_nacl_ipc_browser_fd, false)); // Delay initializing the SyncChannel until after we add filters. This // ensures that the filters won't miss any messages received by @@ -249,10 +266,10 @@ void PpapiDispatcher::OnMsgInitializeNaClDispatcher( new PluginDispatcher(::PPP_GetInterface, args.permissions, args.off_the_record); // The channel handle's true name is not revealed here. - // The second FD (based on NACL_CHROME_DESC_BASE) is the IPC channel to the - // renderer. + DCHECK_NE(g_nacl_ipc_renderer_fd, -1) + << "g_nacl_ipc_renderer_fd must be initialized before the plugin starts"; IPC::ChannelHandle channel_handle( - "nacl", base::FileDescriptor(NACL_CHROME_DESC_BASE + 1, false)); + "nacl", base::FileDescriptor(g_nacl_ipc_renderer_fd, false)); if (!dispatcher->InitPluginWithChannel(this, base::kNullProcessId, channel_handle, false)) { delete dispatcher; @@ -291,24 +308,41 @@ void PpapiDispatcher::SetPpapiKeepAliveThrottleFromCommandLine() { } // namespace +void SetIPCFileDescriptors(int ipc_browser_fd, int ipc_renderer_fd) { + g_nacl_ipc_browser_fd = ipc_browser_fd; + g_nacl_ipc_renderer_fd = ipc_renderer_fd; +} + void PpapiPluginRegisterThreadCreator( const struct PP_ThreadFunctions* thread_functions) { +#if defined(__native_client__) + // TODO(hidehiko): The thread creation for the PPB_Audio is not yet + // implemented on non-SFI mode. Support this. Now, this function invocation + // is just ignored. + // Initialize all classes that need to create threads that call back into // user code. ppapi::PPB_Audio_Shared::SetThreadFunctions(thread_functions); +#endif } int PpapiPluginMain() { // Though it isn't referenced here, we must instantiate an AtExitManager. base::AtExitManager exit_manager; base::MessageLoop loop; +#if defined(IPC_MESSAGE_LOG_ENABLED) IPC::Logging::set_log_function_map(&g_log_function_mapping); +#endif ppapi::proxy::PluginGlobals plugin_globals; base::Thread io_thread("Chrome_NaClIOThread"); base::Thread::Options options; options.message_loop_type = base::MessageLoop::TYPE_IO; io_thread.StartWithOptions(options); +#if defined(__native_client__) + // Currently on non-SFI mode, we don't use SRPC server on plugin. + // TODO(hidehiko): Make sure this SRPC is actually used on SFI-mode. + // Start up the SRPC server on another thread. Otherwise, when it blocks // on an RPC, the PPAPI proxy will hang. Do this before we initialize the // module and start the PPAPI proxy so that the NaCl plugin can continue @@ -317,6 +351,7 @@ int PpapiPluginMain() { if (!NaClSrpcAcceptClientOnThread(srpc_methods)) { return 1; } +#endif PpapiDispatcher ppapi_dispatcher(io_thread.message_loop_proxy()); plugin_globals.set_plugin_proxy_delegate(&ppapi_dispatcher); diff --git a/ppapi/proxy/plugin_main_irt.h b/ppapi/proxy/plugin_main_irt.h new file mode 100644 index 0000000..f9a24cb --- /dev/null +++ b/ppapi/proxy/plugin_main_irt.h @@ -0,0 +1,31 @@ +// Copyright 2014 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. + +#ifndef PPAPI_PROXY_PLUGIN_MAIN_IRT_H_ +#define PPAPI_PROXY_PLUGIN_MAIN_IRT_H_ + +#include "ppapi/nacl_irt/irt_ppapi.h" +#include "ppapi/proxy/ppapi_proxy_export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// The entry point for the main thread of the PPAPI plugin process. +PPAPI_PROXY_EXPORT int PpapiPluginMain(void); + +PPAPI_PROXY_EXPORT void PpapiPluginRegisterThreadCreator( + const struct PP_ThreadFunctions* new_funcs); + +// Sets the IPC channels for the browser and the renderer by the given FD +// numbers. This will be used for non-SFI mode. Must be called before +// PpapiPluginMain is called. +PPAPI_PROXY_EXPORT void SetIPCFileDescriptors( + int browser_ipc_fd, int renderer_ipc_fd); + +#ifdef __cplusplus +} +#endif + +#endif // PPAPI_PROXY_PLUGIN_MAIN_IRT_H_ |