OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/nacl/nacl_listener.h" | 5 #include "chrome/nacl/nacl_listener.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
13 #include "chrome/common/nacl_messages.h" | 13 #include "chrome/common/nacl_messages.h" |
14 #include "ipc/ipc_channel.h" | 14 #include "ipc/ipc_channel.h" |
15 #include "ipc/ipc_switches.h" | 15 #include "ipc/ipc_switches.h" |
16 #include "native_client/src/shared/imc/nacl_imc.h" | |
17 #include "native_client/src/trusted/service_runtime/sel_main_chrome.h" | 16 #include "native_client/src/trusted/service_runtime/sel_main_chrome.h" |
18 | 17 |
19 #if defined(OS_LINUX) | 18 #if defined(OS_LINUX) |
20 #include "content/public/common/child_process_sandbox_support_linux.h" | 19 #include "content/public/common/child_process_sandbox_support_linux.h" |
21 #endif | 20 #endif |
22 | 21 |
23 #if defined(OS_WIN) | 22 #if defined(OS_WIN) |
24 #include <fcntl.h> | 23 #include <fcntl.h> |
25 #include <io.h> | 24 #include <io.h> |
26 #endif | 25 #endif |
27 | 26 |
| 27 namespace { |
28 #if defined(OS_MACOSX) | 28 #if defined(OS_MACOSX) |
29 namespace { | |
30 | 29 |
31 // On Mac OS X, shm_open() works in the sandbox but does not give us | 30 // On Mac OS X, shm_open() works in the sandbox but does not give us |
32 // an FD that we can map as PROT_EXEC. Rather than doing an IPC to | 31 // an FD that we can map as PROT_EXEC. Rather than doing an IPC to |
33 // get an executable SHM region when CreateMemoryObject() is called, | 32 // get an executable SHM region when CreateMemoryObject() is called, |
34 // we preallocate one on startup, since NaCl's sel_ldr only needs one | 33 // we preallocate one on startup, since NaCl's sel_ldr only needs one |
35 // of them. This saves a round trip. | 34 // of them. This saves a round trip. |
36 | 35 |
37 base::subtle::Atomic32 g_shm_fd = -1; | 36 base::subtle::Atomic32 g_shm_fd = -1; |
38 | 37 |
39 int CreateMemoryObject(size_t size, bool executable) { | 38 int CreateMemoryObject(size_t size, int executable) { |
40 if (executable && size > 0) { | 39 if (executable && size > 0) { |
41 int result_fd = base::subtle::NoBarrier_AtomicExchange(&g_shm_fd, -1); | 40 int result_fd = base::subtle::NoBarrier_AtomicExchange(&g_shm_fd, -1); |
42 if (result_fd != -1) { | 41 if (result_fd != -1) { |
43 // ftruncate() is disallowed by the Mac OS X sandbox and | 42 // ftruncate() is disallowed by the Mac OS X sandbox and |
44 // returns EPERM. Luckily, we can get the same effect with | 43 // returns EPERM. Luckily, we can get the same effect with |
45 // lseek() + write(). | 44 // lseek() + write(). |
46 if (lseek(result_fd, size - 1, SEEK_SET) == -1) { | 45 if (lseek(result_fd, size - 1, SEEK_SET) == -1) { |
47 LOG(ERROR) << "lseek() failed: " << errno; | 46 LOG(ERROR) << "lseek() failed: " << errno; |
48 return -1; | 47 return -1; |
49 } | 48 } |
50 if (write(result_fd, "", 1) != 1) { | 49 if (write(result_fd, "", 1) != 1) { |
51 LOG(ERROR) << "write() failed: " << errno; | 50 LOG(ERROR) << "write() failed: " << errno; |
52 return -1; | 51 return -1; |
53 } | 52 } |
54 return result_fd; | 53 return result_fd; |
55 } | 54 } |
56 } | 55 } |
57 // Fall back to NaCl's default implementation. | 56 // Fall back to NaCl's default implementation. |
58 return -1; | 57 return -1; |
59 } | 58 } |
60 | 59 |
| 60 #elif defined(OS_LINUX) |
| 61 |
| 62 int CreateMemoryObject(size_t size, int executable) { |
| 63 return content::MakeSharedMemorySegmentViaIPC(size, executable); |
| 64 } |
| 65 |
| 66 #endif |
61 } // namespace | 67 } // namespace |
62 #endif // defined(OS_MACOSX) | |
63 | 68 |
64 NaClListener::NaClListener() : debug_enabled_(false) {} | 69 NaClListener::NaClListener() : debug_enabled_(false) {} |
65 | 70 |
66 NaClListener::~NaClListener() {} | 71 NaClListener::~NaClListener() {} |
67 | 72 |
68 void NaClListener::Listen() { | 73 void NaClListener::Listen() { |
69 std::string channel_name = | 74 std::string channel_name = |
70 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 75 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
71 switches::kProcessChannelID); | 76 switches::kProcessChannelID); |
72 IPC::Channel channel(channel_name, IPC::Channel::MODE_CLIENT, this); | 77 IPC::Channel channel(channel_name, IPC::Channel::MODE_CLIENT, this); |
73 CHECK(channel.Connect()); | 78 CHECK(channel.Connect()); |
74 MessageLoop::current()->Run(); | 79 MessageLoop::current()->Run(); |
75 } | 80 } |
76 | 81 |
77 bool NaClListener::OnMessageReceived(const IPC::Message& msg) { | 82 bool NaClListener::OnMessageReceived(const IPC::Message& msg) { |
78 bool handled = true; | 83 bool handled = true; |
79 IPC_BEGIN_MESSAGE_MAP(NaClListener, msg) | 84 IPC_BEGIN_MESSAGE_MAP(NaClListener, msg) |
80 IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStartSelLdr) | 85 IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStartSelLdr) |
81 IPC_MESSAGE_UNHANDLED(handled = false) | 86 IPC_MESSAGE_UNHANDLED(handled = false) |
82 IPC_END_MESSAGE_MAP() | 87 IPC_END_MESSAGE_MAP() |
83 return handled; | 88 return handled; |
84 } | 89 } |
85 | 90 |
86 void NaClListener::OnStartSelLdr(std::vector<nacl::FileDescriptor> handles) { | 91 void NaClListener::OnStartSelLdr(std::vector<nacl::FileDescriptor> handles) { |
87 #if defined(OS_LINUX) | 92 struct NaClChromeMainArgs *args = NaClChromeMainArgsCreate(); |
88 nacl::SetCreateMemoryObjectFunc(content::MakeSharedMemorySegmentViaIPC); | 93 if (args == NULL) { |
89 #elif defined(OS_MACOSX) | 94 LOG(ERROR) << "NaClChromeMainArgsCreate() failed"; |
90 nacl::SetCreateMemoryObjectFunc(CreateMemoryObject); | 95 return; |
| 96 } |
| 97 |
| 98 #if defined(OS_LINUX) || defined(OS_MACOSX) |
| 99 args->create_memory_object_func = CreateMemoryObject; |
| 100 # if defined(OS_MACOSX) |
91 CHECK(handles.size() >= 1); | 101 CHECK(handles.size() >= 1); |
92 g_shm_fd = nacl::ToNativeHandle(handles[handles.size() - 1]); | 102 g_shm_fd = nacl::ToNativeHandle(handles[handles.size() - 1]); |
93 handles.pop_back(); | 103 handles.pop_back(); |
| 104 # endif |
94 #endif | 105 #endif |
95 | 106 |
96 CHECK(handles.size() >= 1); | 107 CHECK(handles.size() >= 1); |
97 NaClHandle irt_handle = nacl::ToNativeHandle(handles[handles.size() - 1]); | 108 NaClHandle irt_handle = nacl::ToNativeHandle(handles[handles.size() - 1]); |
98 handles.pop_back(); | 109 handles.pop_back(); |
99 | 110 |
100 #if defined(OS_WIN) | 111 #if defined(OS_WIN) |
101 int irt_desc = _open_osfhandle(reinterpret_cast<intptr_t>(irt_handle), | 112 args->irt_fd = _open_osfhandle(reinterpret_cast<intptr_t>(irt_handle), |
102 _O_RDONLY | _O_BINARY); | 113 _O_RDONLY | _O_BINARY); |
103 if (irt_desc < 0) { | 114 if (args->irt_fd < 0) { |
104 LOG(ERROR) << "_open_osfhandle() failed"; | 115 LOG(ERROR) << "_open_osfhandle() failed"; |
105 return; | 116 return; |
106 } | 117 } |
107 #else | 118 #else |
108 int irt_desc = irt_handle; | 119 args->irt_fd = irt_handle; |
109 #endif | 120 #endif |
110 | 121 |
111 NaClSetIrtFileDesc(irt_desc); | 122 CHECK(handles.size() == 1); |
112 | 123 args->imc_bootstrap_handle = nacl::ToNativeHandle(handles[0]); |
113 scoped_array<NaClHandle> array(new NaClHandle[handles.size()]); | 124 args->enable_debug_stub = debug_enabled_; |
114 for (size_t i = 0; i < handles.size(); i++) { | 125 NaClChromeMainStart(args); |
115 array[i] = nacl::ToNativeHandle(handles[i]); | |
116 } | |
117 NaClMainForChromium(static_cast<int>(handles.size()), array.get(), | |
118 debug_enabled_); | |
119 NOTREACHED(); | 126 NOTREACHED(); |
120 } | 127 } |
OLD | NEW |