| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/nacl/loader/nacl_listener.h" | 5 #include "components/nacl/loader/nacl_listener.h" |
| 6 | 6 |
| 7 #include <errno.h> | |
| 8 #include <fcntl.h> | |
| 9 #include <stdlib.h> | |
| 10 | |
| 11 #if defined(OS_POSIX) | |
| 12 #include <unistd.h> | |
| 13 #endif | |
| 14 | |
| 15 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 16 #include "base/logging.h" | 8 #include "base/logging.h" |
| 17 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 18 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| 19 #include "base/rand_util.h" | |
| 20 #include "components/nacl/common/nacl_messages.h" | 11 #include "components/nacl/common/nacl_messages.h" |
| 21 #include "components/nacl/loader/nacl_ipc_adapter.h" | 12 #include "components/nacl/loader/listener_delegate.h" |
| 22 #include "components/nacl/loader/nacl_validation_db.h" | |
| 23 #include "components/nacl/loader/nacl_validation_query.h" | |
| 24 #include "ipc/ipc_channel_handle.h" | 13 #include "ipc/ipc_channel_handle.h" |
| 25 #include "ipc/ipc_switches.h" | 14 #include "ipc/ipc_switches.h" |
| 26 #include "ipc/ipc_sync_channel.h" | 15 #include "ipc/ipc_sync_channel.h" |
| 27 #include "ipc/ipc_sync_message_filter.h" | 16 #include "ipc/ipc_sync_message_filter.h" |
| 28 #include "native_client/src/public/chrome_main.h" | |
| 29 #include "native_client/src/public/nacl_app.h" | |
| 30 #include "native_client/src/public/nacl_file_info.h" | |
| 31 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h" | |
| 32 | |
| 33 #if defined(OS_POSIX) | |
| 34 #include "base/file_descriptor_posix.h" | |
| 35 #endif | |
| 36 | |
| 37 #if defined(OS_LINUX) | |
| 38 #include "components/nacl/loader/nonsfi/irt_random.h" | |
| 39 #include "components/nacl/loader/nonsfi/nonsfi_main.h" | |
| 40 #include "content/public/common/child_process_sandbox_support_linux.h" | |
| 41 #include "ppapi/nacl_irt/plugin_startup.h" | |
| 42 #endif | |
| 43 | |
| 44 #if defined(OS_WIN) | |
| 45 #include <fcntl.h> | |
| 46 #include <io.h> | |
| 47 | |
| 48 #include "content/public/common/sandbox_init.h" | |
| 49 #endif | |
| 50 | |
| 51 namespace { | |
| 52 #if defined(OS_MACOSX) | |
| 53 | |
| 54 // On Mac OS X, shm_open() works in the sandbox but does not give us | |
| 55 // an FD that we can map as PROT_EXEC. Rather than doing an IPC to | |
| 56 // get an executable SHM region when CreateMemoryObject() is called, | |
| 57 // we preallocate one on startup, since NaCl's sel_ldr only needs one | |
| 58 // of them. This saves a round trip. | |
| 59 | |
| 60 base::subtle::Atomic32 g_shm_fd = -1; | |
| 61 | |
| 62 int CreateMemoryObject(size_t size, int executable) { | |
| 63 if (executable && size > 0) { | |
| 64 int result_fd = base::subtle::NoBarrier_AtomicExchange(&g_shm_fd, -1); | |
| 65 if (result_fd != -1) { | |
| 66 // ftruncate() is disallowed by the Mac OS X sandbox and | |
| 67 // returns EPERM. Luckily, we can get the same effect with | |
| 68 // lseek() + write(). | |
| 69 if (lseek(result_fd, size - 1, SEEK_SET) == -1) { | |
| 70 LOG(ERROR) << "lseek() failed: " << errno; | |
| 71 return -1; | |
| 72 } | |
| 73 if (write(result_fd, "", 1) != 1) { | |
| 74 LOG(ERROR) << "write() failed: " << errno; | |
| 75 return -1; | |
| 76 } | |
| 77 return result_fd; | |
| 78 } | |
| 79 } | |
| 80 // Fall back to NaCl's default implementation. | |
| 81 return -1; | |
| 82 } | |
| 83 | |
| 84 #elif defined(OS_LINUX) | |
| 85 | |
| 86 int CreateMemoryObject(size_t size, int executable) { | |
| 87 return content::MakeSharedMemorySegmentViaIPC(size, executable); | |
| 88 } | |
| 89 | |
| 90 #elif defined(OS_WIN) | |
| 91 | |
| 92 NaClListener* g_listener; | |
| 93 | |
| 94 // We wrap the function to convert the bool return value to an int. | |
| 95 int BrokerDuplicateHandle(NaClHandle source_handle, | |
| 96 uint32_t process_id, | |
| 97 NaClHandle* target_handle, | |
| 98 uint32_t desired_access, | |
| 99 uint32_t options) { | |
| 100 return content::BrokerDuplicateHandle(source_handle, process_id, | |
| 101 target_handle, desired_access, | |
| 102 options); | |
| 103 } | |
| 104 | |
| 105 int AttachDebugExceptionHandler(const void* info, size_t info_size) { | |
| 106 std::string info_string(reinterpret_cast<const char*>(info), info_size); | |
| 107 bool result = false; | |
| 108 if (!g_listener->Send(new NaClProcessMsg_AttachDebugExceptionHandler( | |
| 109 info_string, &result))) | |
| 110 return false; | |
| 111 return result; | |
| 112 } | |
| 113 | |
| 114 void DebugStubPortSelectedHandler(uint16_t port) { | |
| 115 g_listener->Send(new NaClProcessHostMsg_DebugStubPortSelected(port)); | |
| 116 } | |
| 117 | |
| 118 #endif | |
| 119 | |
| 120 // Creates the PPAPI IPC channel between the NaCl IRT and the host | |
| 121 // (browser/renderer) process, and starts to listen it on the thread where | |
| 122 // the given message_loop_proxy runs. | |
| 123 // Also, creates and sets the corresponding NaClDesc to the given nap with | |
| 124 // the FD #. | |
| 125 void SetUpIPCAdapter(IPC::ChannelHandle* handle, | |
| 126 scoped_refptr<base::MessageLoopProxy> message_loop_proxy, | |
| 127 struct NaClApp* nap, | |
| 128 int nacl_fd) { | |
| 129 scoped_refptr<NaClIPCAdapter> ipc_adapter( | |
| 130 new NaClIPCAdapter(*handle, message_loop_proxy.get())); | |
| 131 ipc_adapter->ConnectChannel(); | |
| 132 #if defined(OS_POSIX) | |
| 133 handle->socket = | |
| 134 base::FileDescriptor(ipc_adapter->TakeClientFileDescriptor(), true); | |
| 135 #endif | |
| 136 | |
| 137 // Pass a NaClDesc to the untrusted side. This will hold a ref to the | |
| 138 // NaClIPCAdapter. | |
| 139 NaClAppSetDesc(nap, nacl_fd, ipc_adapter->MakeNaClDesc()); | |
| 140 } | |
| 141 | |
| 142 } // namespace | |
| 143 | |
| 144 class BrowserValidationDBProxy : public NaClValidationDB { | |
| 145 public: | |
| 146 explicit BrowserValidationDBProxy(NaClListener* listener) | |
| 147 : listener_(listener) { | |
| 148 } | |
| 149 | |
| 150 virtual bool QueryKnownToValidate(const std::string& signature) OVERRIDE { | |
| 151 // Initialize to false so that if the Send fails to write to the return | |
| 152 // value we're safe. For example if the message is (for some reason) | |
| 153 // dispatched as an async message the return parameter will not be written. | |
| 154 bool result = false; | |
| 155 if (!listener_->Send(new NaClProcessMsg_QueryKnownToValidate(signature, | |
| 156 &result))) { | |
| 157 LOG(ERROR) << "Failed to query NaCl validation cache."; | |
| 158 result = false; | |
| 159 } | |
| 160 return result; | |
| 161 } | |
| 162 | |
| 163 virtual void SetKnownToValidate(const std::string& signature) OVERRIDE { | |
| 164 // Caching is optional: NaCl will still work correctly if the IPC fails. | |
| 165 if (!listener_->Send(new NaClProcessMsg_SetKnownToValidate(signature))) { | |
| 166 LOG(ERROR) << "Failed to update NaCl validation cache."; | |
| 167 } | |
| 168 } | |
| 169 | |
| 170 virtual bool ResolveFileToken(struct NaClFileToken* file_token, | |
| 171 int32* fd, std::string* path) OVERRIDE { | |
| 172 *fd = -1; | |
| 173 *path = ""; | |
| 174 if (!NaClFileTokenIsValid(file_token)) { | |
| 175 return false; | |
| 176 } | |
| 177 IPC::PlatformFileForTransit ipc_fd = IPC::InvalidPlatformFileForTransit(); | |
| 178 base::FilePath ipc_path; | |
| 179 if (!listener_->Send(new NaClProcessMsg_ResolveFileToken(file_token->lo, | |
| 180 file_token->hi, | |
| 181 &ipc_fd, | |
| 182 &ipc_path))) { | |
| 183 return false; | |
| 184 } | |
| 185 if (ipc_fd == IPC::InvalidPlatformFileForTransit()) { | |
| 186 return false; | |
| 187 } | |
| 188 base::PlatformFile handle = | |
| 189 IPC::PlatformFileForTransitToPlatformFile(ipc_fd); | |
| 190 #if defined(OS_WIN) | |
| 191 // On Windows, valid handles are 32 bit unsigned integers so this is safe. | |
| 192 *fd = reinterpret_cast<uintptr_t>(handle); | |
| 193 #else | |
| 194 *fd = handle; | |
| 195 #endif | |
| 196 // It doesn't matter if the path is invalid UTF8 as long as it's consistent | |
| 197 // and unforgeable. | |
| 198 *path = ipc_path.AsUTF8Unsafe(); | |
| 199 return true; | |
| 200 } | |
| 201 | |
| 202 private: | |
| 203 // The listener never dies, otherwise this might be a dangling reference. | |
| 204 NaClListener* listener_; | |
| 205 }; | |
| 206 | 17 |
| 207 | 18 |
| 208 NaClListener::NaClListener() : shutdown_event_(true, false), | 19 NaClListener::NaClListener(scoped_ptr<nacl::ListenerDelegate> delegate) |
| 209 io_thread_("NaCl_IOThread"), | 20 : delegate_(delegate.Pass()), |
| 210 uses_nonsfi_mode_(false), | 21 shutdown_event_(true, false), |
| 211 #if defined(OS_LINUX) | 22 io_thread_("NaCl_IOThread"), |
| 212 prereserved_sandbox_size_(0), | 23 main_loop_(NULL) { |
| 213 #endif | |
| 214 #if defined(OS_POSIX) | |
| 215 number_of_cores_(-1), // unknown/error | |
| 216 #endif | |
| 217 main_loop_(NULL) { | |
| 218 io_thread_.StartWithOptions( | 24 io_thread_.StartWithOptions( |
| 219 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); | 25 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
| 220 #if defined(OS_WIN) | |
| 221 DCHECK(g_listener == NULL); | |
| 222 g_listener = this; | |
| 223 #endif | |
| 224 } | 26 } |
| 225 | 27 |
| 226 NaClListener::~NaClListener() { | 28 NaClListener::~NaClListener() { |
| 227 NOTREACHED(); | 29 NOTREACHED(); |
| 228 shutdown_event_.Signal(); | 30 shutdown_event_.Signal(); |
| 229 #if defined(OS_WIN) | |
| 230 g_listener = NULL; | |
| 231 #endif | |
| 232 } | 31 } |
| 233 | 32 |
| 234 bool NaClListener::Send(IPC::Message* msg) { | 33 bool NaClListener::Send(IPC::Message* msg) { |
| 235 DCHECK(main_loop_ != NULL); | 34 DCHECK(main_loop_ != NULL); |
| 236 if (base::MessageLoop::current() == main_loop_) { | 35 if (base::MessageLoop::current() == main_loop_) { |
| 237 // This thread owns the channel. | 36 // This thread owns the channel. |
| 238 return channel_->Send(msg); | 37 return channel_->Send(msg); |
| 239 } else { | 38 } else { |
| 240 // This thread does not own the channel. | 39 // This thread does not own the channel. |
| 241 return filter_->Send(msg); | 40 return filter_->Send(msg); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 258 bool NaClListener::OnMessageReceived(const IPC::Message& msg) { | 57 bool NaClListener::OnMessageReceived(const IPC::Message& msg) { |
| 259 bool handled = true; | 58 bool handled = true; |
| 260 IPC_BEGIN_MESSAGE_MAP(NaClListener, msg) | 59 IPC_BEGIN_MESSAGE_MAP(NaClListener, msg) |
| 261 IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart) | 60 IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart) |
| 262 IPC_MESSAGE_UNHANDLED(handled = false) | 61 IPC_MESSAGE_UNHANDLED(handled = false) |
| 263 IPC_END_MESSAGE_MAP() | 62 IPC_END_MESSAGE_MAP() |
| 264 return handled; | 63 return handled; |
| 265 } | 64 } |
| 266 | 65 |
| 267 void NaClListener::OnStart(const nacl::NaClStartParams& params) { | 66 void NaClListener::OnStart(const nacl::NaClStartParams& params) { |
| 268 if (uses_nonsfi_mode_) { | 67 delegate_->Start( |
| 269 StartNonSfi(params); | 68 params, io_thread_.message_loop_proxy(), CreateTrustedListener(), this); |
| 270 return; | |
| 271 } | |
| 272 | |
| 273 #if defined(OS_LINUX) || defined(OS_MACOSX) | |
| 274 int urandom_fd = dup(base::GetUrandomFD()); | |
| 275 if (urandom_fd < 0) { | |
| 276 LOG(ERROR) << "Failed to dup() the urandom FD"; | |
| 277 return; | |
| 278 } | |
| 279 NaClChromeMainSetUrandomFd(urandom_fd); | |
| 280 #endif | |
| 281 | |
| 282 struct NaClApp* nap = NULL; | |
| 283 NaClChromeMainInit(); | |
| 284 nap = NaClAppCreate(); | |
| 285 if (nap == NULL) { | |
| 286 LOG(ERROR) << "NaClAppCreate() failed"; | |
| 287 return; | |
| 288 } | |
| 289 | |
| 290 IPC::ChannelHandle browser_handle; | |
| 291 IPC::ChannelHandle ppapi_renderer_handle; | |
| 292 | |
| 293 if (params.enable_ipc_proxy) { | |
| 294 browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
| 295 ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
| 296 | |
| 297 // Create the PPAPI IPC channels between the NaCl IRT and the host | |
| 298 // (browser/renderer) processes. The IRT uses these channels to | |
| 299 // communicate with the host and to initialize the IPC dispatchers. | |
| 300 SetUpIPCAdapter(&browser_handle, io_thread_.message_loop_proxy(), | |
| 301 nap, NACL_CHROME_DESC_BASE); | |
| 302 SetUpIPCAdapter(&ppapi_renderer_handle, io_thread_.message_loop_proxy(), | |
| 303 nap, NACL_CHROME_DESC_BASE + 1); | |
| 304 } | |
| 305 | |
| 306 IPC::ChannelHandle trusted_renderer_handle = CreateTrustedListener( | |
| 307 io_thread_.message_loop_proxy(), &shutdown_event_); | |
| 308 if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( | |
| 309 browser_handle, ppapi_renderer_handle, | |
| 310 trusted_renderer_handle, IPC::ChannelHandle()))) | |
| 311 LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; | |
| 312 | |
| 313 std::vector<nacl::FileDescriptor> handles = params.handles; | |
| 314 struct NaClChromeMainArgs* args = NaClChromeMainArgsCreate(); | |
| 315 if (args == NULL) { | |
| 316 LOG(ERROR) << "NaClChromeMainArgsCreate() failed"; | |
| 317 return; | |
| 318 } | |
| 319 | |
| 320 #if defined(OS_LINUX) || defined(OS_MACOSX) | |
| 321 args->number_of_cores = number_of_cores_; | |
| 322 args->create_memory_object_func = CreateMemoryObject; | |
| 323 # if defined(OS_MACOSX) | |
| 324 CHECK(handles.size() >= 1); | |
| 325 g_shm_fd = nacl::ToNativeHandle(handles[handles.size() - 1]); | |
| 326 handles.pop_back(); | |
| 327 # endif | |
| 328 #endif | |
| 329 | |
| 330 if (params.uses_irt) { | |
| 331 CHECK(handles.size() >= 1); | |
| 332 NaClHandle irt_handle = nacl::ToNativeHandle(handles[handles.size() - 1]); | |
| 333 handles.pop_back(); | |
| 334 | |
| 335 #if defined(OS_WIN) | |
| 336 args->irt_fd = _open_osfhandle(reinterpret_cast<intptr_t>(irt_handle), | |
| 337 _O_RDONLY | _O_BINARY); | |
| 338 if (args->irt_fd < 0) { | |
| 339 LOG(ERROR) << "_open_osfhandle() failed"; | |
| 340 return; | |
| 341 } | |
| 342 #else | |
| 343 args->irt_fd = irt_handle; | |
| 344 #endif | |
| 345 } else { | |
| 346 // Otherwise, the IRT handle is not even sent. | |
| 347 args->irt_fd = -1; | |
| 348 } | |
| 349 | |
| 350 if (params.validation_cache_enabled) { | |
| 351 // SHA256 block size. | |
| 352 CHECK_EQ(params.validation_cache_key.length(), (size_t) 64); | |
| 353 // The cache structure is not freed and exists until the NaCl process exits. | |
| 354 args->validation_cache = CreateValidationCache( | |
| 355 new BrowserValidationDBProxy(this), params.validation_cache_key, | |
| 356 params.version); | |
| 357 } | |
| 358 | |
| 359 CHECK(handles.size() == 1); | |
| 360 args->imc_bootstrap_handle = nacl::ToNativeHandle(handles[0]); | |
| 361 args->enable_exception_handling = params.enable_exception_handling; | |
| 362 args->enable_debug_stub = params.enable_debug_stub; | |
| 363 args->enable_dyncode_syscalls = params.enable_dyncode_syscalls; | |
| 364 if (!params.enable_dyncode_syscalls) { | |
| 365 // Bound the initial nexe's code segment size under PNaCl to | |
| 366 // reduce the chance of a code spraying attack succeeding (see | |
| 367 // https://code.google.com/p/nativeclient/issues/detail?id=3572). | |
| 368 // We assume that !params.enable_dyncode_syscalls is synonymous | |
| 369 // with PNaCl. We can't apply this arbitrary limit outside of | |
| 370 // PNaCl because it might break existing NaCl apps, and this limit | |
| 371 // is only useful if the dyncode syscalls are disabled. | |
| 372 args->initial_nexe_max_code_bytes = 64 << 20; // 64 MB | |
| 373 | |
| 374 // Indicate that this is a PNaCl module. | |
| 375 // TODO(jvoung): Plumb through something indicating that this is PNaCl | |
| 376 // instead of relying on enable_dyncode_syscalls. | |
| 377 args->pnacl_mode = 1; | |
| 378 } | |
| 379 #if defined(OS_LINUX) || defined(OS_MACOSX) | |
| 380 args->debug_stub_server_bound_socket_fd = nacl::ToNativeHandle( | |
| 381 params.debug_stub_server_bound_socket); | |
| 382 #endif | |
| 383 #if defined(OS_WIN) | |
| 384 args->broker_duplicate_handle_func = BrokerDuplicateHandle; | |
| 385 args->attach_debug_exception_handler_func = AttachDebugExceptionHandler; | |
| 386 args->debug_stub_server_port_selected_handler_func = | |
| 387 DebugStubPortSelectedHandler; | |
| 388 #endif | |
| 389 #if defined(OS_LINUX) | |
| 390 args->prereserved_sandbox_size = prereserved_sandbox_size_; | |
| 391 #endif | |
| 392 | |
| 393 NaClFileInfo nexe_file_info; | |
| 394 base::PlatformFile nexe_file = IPC::PlatformFileForTransitToPlatformFile( | |
| 395 params.nexe_file); | |
| 396 #if defined(OS_WIN) | |
| 397 nexe_file_info.desc = | |
| 398 _open_osfhandle(reinterpret_cast<intptr_t>(nexe_file), | |
| 399 _O_RDONLY | _O_BINARY); | |
| 400 #elif defined(OS_POSIX) | |
| 401 nexe_file_info.desc = nexe_file; | |
| 402 #else | |
| 403 #error Unsupported target platform. | |
| 404 #endif | |
| 405 nexe_file_info.file_token.lo = params.nexe_token_lo; | |
| 406 nexe_file_info.file_token.hi = params.nexe_token_hi; | |
| 407 args->nexe_desc = NaClDescIoFromFileInfo(nexe_file_info, NACL_ABI_O_RDONLY); | |
| 408 | |
| 409 NaClChromeMainStartApp(nap, args); | |
| 410 } | 69 } |
| 411 | 70 |
| 412 void NaClListener::StartNonSfi(const nacl::NaClStartParams& params) { | 71 IPC::ChannelHandle NaClListener::CreateTrustedListener() { |
| 413 #if !defined(OS_LINUX) | |
| 414 NOTREACHED() << "Non-SFI NaCl is only supported on Linux"; | |
| 415 #else | |
| 416 // Random number source initialization. | |
| 417 nacl::nonsfi::SetUrandomFd(base::GetUrandomFD()); | |
| 418 | |
| 419 IPC::ChannelHandle browser_handle; | |
| 420 IPC::ChannelHandle ppapi_renderer_handle; | |
| 421 IPC::ChannelHandle manifest_service_handle; | |
| 422 | |
| 423 if (params.enable_ipc_proxy) { | |
| 424 browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
| 425 ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
| 426 manifest_service_handle = | |
| 427 IPC::Channel::GenerateVerifiedChannelID("nacl"); | |
| 428 | |
| 429 // In non-SFI mode, we neither intercept nor rewrite the message using | |
| 430 // NaClIPCAdapter, and the channels are connected between the plugin and | |
| 431 // the hosts directly. So, the IPC::Channel instances will be created in | |
| 432 // the plugin side, because the IPC::Listener needs to live on the | |
| 433 // plugin's main thread. However, on initialization (i.e. before loading | |
| 434 // the plugin binary), the FD needs to be passed to the hosts. So, here | |
| 435 // we create raw FD pairs, and pass the client side FDs to the hosts, | |
| 436 // and the server side FDs to the plugin. | |
| 437 int browser_server_ppapi_fd; | |
| 438 int browser_client_ppapi_fd; | |
| 439 int renderer_server_ppapi_fd; | |
| 440 int renderer_client_ppapi_fd; | |
| 441 int manifest_service_server_fd; | |
| 442 int manifest_service_client_fd; | |
| 443 if (!IPC::SocketPair( | |
| 444 &browser_server_ppapi_fd, &browser_client_ppapi_fd) || | |
| 445 !IPC::SocketPair( | |
| 446 &renderer_server_ppapi_fd, &renderer_client_ppapi_fd) || | |
| 447 !IPC::SocketPair( | |
| 448 &manifest_service_server_fd, &manifest_service_client_fd)) { | |
| 449 LOG(ERROR) << "Failed to create sockets for IPC."; | |
| 450 return; | |
| 451 } | |
| 452 | |
| 453 // Set the plugin IPC channel FDs. | |
| 454 ppapi::SetIPCFileDescriptors(browser_server_ppapi_fd, | |
| 455 renderer_server_ppapi_fd, | |
| 456 manifest_service_server_fd); | |
| 457 ppapi::StartUpPlugin(); | |
| 458 | |
| 459 // Send back to the client side IPC channel FD to the host. | |
| 460 browser_handle.socket = | |
| 461 base::FileDescriptor(browser_client_ppapi_fd, true); | |
| 462 ppapi_renderer_handle.socket = | |
| 463 base::FileDescriptor(renderer_client_ppapi_fd, true); | |
| 464 manifest_service_handle.socket = | |
| 465 base::FileDescriptor(manifest_service_client_fd, true); | |
| 466 } | |
| 467 | |
| 468 // TODO(teravest): Do we plan on using this renderer handle for nexe loading | |
| 469 // for non-SFI? Right now, passing an empty channel handle instead causes | |
| 470 // hangs, so we'll keep it. | |
| 471 IPC::ChannelHandle trusted_renderer_handle = CreateTrustedListener( | |
| 472 io_thread_.message_loop_proxy(), &shutdown_event_); | |
| 473 if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( | |
| 474 browser_handle, ppapi_renderer_handle, | |
| 475 trusted_renderer_handle, manifest_service_handle))) | |
| 476 LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; | |
| 477 | |
| 478 // Ensure that the validation cache key (used as an extra input to the | |
| 479 // validation cache's hashing) isn't exposed accidentally. | |
| 480 CHECK(!params.validation_cache_enabled); | |
| 481 CHECK(params.validation_cache_key.size() == 0); | |
| 482 CHECK(params.version.size() == 0); | |
| 483 // Ensure that a debug stub FD isn't passed through accidentally. | |
| 484 CHECK(!params.enable_debug_stub); | |
| 485 CHECK(params.debug_stub_server_bound_socket.fd == -1); | |
| 486 | |
| 487 CHECK(!params.uses_irt); | |
| 488 CHECK(params.handles.empty()); | |
| 489 | |
| 490 CHECK(params.nexe_file != IPC::InvalidPlatformFileForTransit()); | |
| 491 CHECK(params.nexe_token_lo == 0); | |
| 492 CHECK(params.nexe_token_hi == 0); | |
| 493 nacl::nonsfi::MainStart( | |
| 494 IPC::PlatformFileForTransitToPlatformFile(params.nexe_file)); | |
| 495 #endif // defined(OS_LINUX) | |
| 496 } | |
| 497 | |
| 498 IPC::ChannelHandle NaClListener::CreateTrustedListener( | |
| 499 base::MessageLoopProxy* message_loop_proxy, | |
| 500 base::WaitableEvent* shutdown_event) { | |
| 501 // The argument passed to GenerateVerifiedChannelID() here MUST be "nacl". | 72 // The argument passed to GenerateVerifiedChannelID() here MUST be "nacl". |
| 502 // Using an alternate channel name prevents the pipe from being created on | 73 // Using an alternate channel name prevents the pipe from being created on |
| 503 // Windows when the sandbox is enabled. | 74 // Windows when the sandbox is enabled. |
| 504 IPC::ChannelHandle trusted_renderer_handle = | 75 IPC::ChannelHandle trusted_channel_handle = |
| 505 IPC::Channel::GenerateVerifiedChannelID("nacl"); | 76 IPC::Channel::GenerateVerifiedChannelID("nacl"); |
| 506 trusted_listener_ = new NaClTrustedListener( | 77 trusted_listener_ = new NaClTrustedListener( |
| 507 trusted_renderer_handle, io_thread_.message_loop_proxy().get()); | 78 trusted_channel_handle, io_thread_.message_loop_proxy()); |
| 508 #if defined(OS_POSIX) | 79 #if defined(OS_POSIX) |
| 509 trusted_renderer_handle.socket = base::FileDescriptor( | 80 trusted_channel_handle.socket = base::FileDescriptor( |
| 510 trusted_listener_->TakeClientFileDescriptor(), true); | 81 trusted_listener_->TakeClientFileDescriptor(), true); |
| 511 #endif | 82 #endif |
| 512 return trusted_renderer_handle; | 83 return trusted_channel_handle; |
| 513 } | 84 } |
| OLD | NEW |