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 |