OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "build/build_config.h" | 5 #include "build/build_config.h" |
6 | 6 |
7 #include "chrome/browser/nacl_host/nacl_process_host.h" | 7 #include "chrome/browser/nacl_host/nacl_process_host.h" |
8 | 8 |
9 #if defined(OS_POSIX) | 9 #if defined(OS_POSIX) |
10 #include <fcntl.h> | 10 #include <fcntl.h> |
11 #endif | 11 #endif |
12 | 12 |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
14 #include "chrome/browser/renderer_host/resource_message_filter.h" | 14 #include "chrome/browser/renderer_host/resource_message_filter.h" |
15 #include "chrome/common/chrome_switches.h" | 15 #include "chrome/common/chrome_switches.h" |
16 #include "chrome/common/logging_chrome.h" | 16 #include "chrome/common/logging_chrome.h" |
17 #include "chrome/common/nacl_cmd_line.h" | 17 #include "chrome/common/nacl_cmd_line.h" |
18 #include "chrome/common/nacl_messages.h" | 18 #include "chrome/common/nacl_messages.h" |
19 #include "chrome/common/render_messages.h" | 19 #include "chrome/common/render_messages.h" |
20 #include "ipc/ipc_switches.h" | 20 #include "ipc/ipc_switches.h" |
21 | 21 |
22 #if defined(OS_POSIX) | 22 #if defined(OS_POSIX) |
23 #include "ipc/ipc_channel_posix.h" | 23 #include "ipc/ipc_channel_posix.h" |
24 #elif defined(OS_WIN) | 24 #elif defined(OS_WIN) |
25 #include "chrome/browser/nacl_host/nacl_broker_service_win.h" | 25 #include "chrome/browser/nacl_host/nacl_broker_service_win.h" |
26 #endif | 26 #endif |
27 | 27 |
| 28 namespace { |
| 29 |
| 30 void SetCloseOnExec(nacl::Handle fd) { |
| 31 #if defined(OS_POSIX) |
| 32 int flags = fcntl(fd, F_GETFD); |
| 33 CHECK(flags != -1); |
| 34 int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC); |
| 35 CHECK(rc == 0); |
| 36 #endif |
| 37 } |
| 38 |
| 39 } // namespace |
| 40 |
28 NaClProcessHost::NaClProcessHost( | 41 NaClProcessHost::NaClProcessHost( |
29 ResourceDispatcherHost *resource_dispatcher_host, | 42 ResourceDispatcherHost *resource_dispatcher_host, |
30 const std::wstring& url) | 43 const std::wstring& url) |
31 : BrowserChildProcessHost(NACL_LOADER_PROCESS, resource_dispatcher_host), | 44 : BrowserChildProcessHost(NACL_LOADER_PROCESS, resource_dispatcher_host), |
32 resource_dispatcher_host_(resource_dispatcher_host), | 45 resource_dispatcher_host_(resource_dispatcher_host), |
33 reply_msg_(NULL), | 46 reply_msg_(NULL), |
34 descriptor_(0), | |
35 running_on_wow64_(false) { | 47 running_on_wow64_(false) { |
36 set_name(url); | 48 set_name(url); |
37 #if defined(OS_WIN) | 49 #if defined(OS_WIN) |
38 CheckIsWow64(); | 50 CheckIsWow64(); |
39 #endif | 51 #endif |
40 } | 52 } |
41 | 53 |
42 NaClProcessHost::~NaClProcessHost() { | 54 NaClProcessHost::~NaClProcessHost() { |
43 if (!reply_msg_) | 55 if (!reply_msg_) |
44 return; | 56 return; |
45 | 57 |
| 58 for (size_t i = 0; i < sockets_for_renderer_.size(); i++) { |
| 59 nacl::Close(sockets_for_renderer_[i]); |
| 60 } |
| 61 for (size_t i = 0; i < sockets_for_sel_ldr_.size(); i++) { |
| 62 nacl::Close(sockets_for_sel_ldr_[i]); |
| 63 } |
| 64 |
46 // OnProcessLaunched didn't get called because the process couldn't launch. | 65 // OnProcessLaunched didn't get called because the process couldn't launch. |
47 // Don't keep the renderer hanging. | 66 // Don't keep the renderer hanging. |
48 reply_msg_->set_reply_error(); | 67 reply_msg_->set_reply_error(); |
49 resource_message_filter_->Send(reply_msg_); | 68 resource_message_filter_->Send(reply_msg_); |
50 } | 69 } |
51 | 70 |
52 bool NaClProcessHost::Launch(ResourceMessageFilter* resource_message_filter, | 71 bool NaClProcessHost::Launch(ResourceMessageFilter* resource_message_filter, |
53 const int descriptor, | 72 int socket_count, |
54 IPC::Message* reply_msg) { | 73 IPC::Message* reply_msg) { |
55 #ifdef DISABLE_NACL | 74 #ifdef DISABLE_NACL |
56 NOTIMPLEMENTED() << "Native Client disabled at build time"; | 75 NOTIMPLEMENTED() << "Native Client disabled at build time"; |
57 return false; | 76 return false; |
58 #else | 77 #else |
59 // Create a connected socket | 78 // Place an arbitrary limit on the number of sockets to limit |
60 if (nacl::SocketPair(pair_) == -1) | 79 // exposure in case the renderer is compromised. We can increase |
61 return false; | 80 // this if necessary. |
62 | 81 if (socket_count > 8) { |
63 // Launch the process | |
64 descriptor_ = descriptor; | |
65 if (!LaunchSelLdr()) { | |
66 nacl::Close(pair_[0]); | |
67 return false; | 82 return false; |
68 } | 83 } |
69 | 84 |
| 85 // Rather than creating a socket pair in the renderer, and passing |
| 86 // one side through the browser to sel_ldr, socket pairs are created |
| 87 // in the browser and then passed to the renderer and sel_ldr. |
| 88 // |
| 89 // This is mainly for the benefit of Windows, where sockets cannot |
| 90 // be passed in messages, but are copied via DuplicateHandle(). |
| 91 // This means the sandboxed renderer cannot send handles to the |
| 92 // browser process. |
| 93 |
| 94 for (int i = 0; i < socket_count; i++) { |
| 95 nacl::Handle pair[2]; |
| 96 // Create a connected socket |
| 97 if (nacl::SocketPair(pair) == -1) |
| 98 return false; |
| 99 sockets_for_renderer_.push_back(pair[0]); |
| 100 sockets_for_sel_ldr_.push_back(pair[1]); |
| 101 SetCloseOnExec(pair[0]); |
| 102 SetCloseOnExec(pair[1]); |
| 103 } |
| 104 |
| 105 // Launch the process |
| 106 if (!LaunchSelLdr()) { |
| 107 return false; |
| 108 } |
| 109 |
70 resource_message_filter_ = resource_message_filter; | 110 resource_message_filter_ = resource_message_filter; |
71 reply_msg_ = reply_msg; | 111 reply_msg_ = reply_msg; |
72 | 112 |
73 return true; | 113 return true; |
74 #endif // DISABLE_NACL | 114 #endif // DISABLE_NACL |
75 } | 115 } |
76 | 116 |
77 bool NaClProcessHost::LaunchSelLdr() { | 117 bool NaClProcessHost::LaunchSelLdr() { |
78 if (!CreateChannel()) | 118 if (!CreateChannel()) |
79 return false; | 119 return false; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 } | 162 } |
123 | 163 |
124 void NaClProcessHost::OnChildDied() { | 164 void NaClProcessHost::OnChildDied() { |
125 #if defined(OS_WIN) | 165 #if defined(OS_WIN) |
126 NaClBrokerService::GetInstance()->OnLoaderDied(); | 166 NaClBrokerService::GetInstance()->OnLoaderDied(); |
127 #endif | 167 #endif |
128 BrowserChildProcessHost::OnChildDied(); | 168 BrowserChildProcessHost::OnChildDied(); |
129 } | 169 } |
130 | 170 |
131 void NaClProcessHost::OnProcessLaunched() { | 171 void NaClProcessHost::OnProcessLaunched() { |
132 nacl::FileDescriptor imc_handle; | 172 std::vector<nacl::FileDescriptor> handles_for_renderer; |
133 base::ProcessHandle nacl_process_handle; | 173 base::ProcessHandle nacl_process_handle; |
| 174 |
| 175 for (size_t i = 0; i < sockets_for_renderer_.size(); i++) { |
134 #if defined(OS_WIN) | 176 #if defined(OS_WIN) |
135 // Duplicate the IMC handle | 177 // Copy the handle into the renderer process. |
136 // We assume the size of imc_handle has the same size as HANDLE, so the cast | 178 HANDLE handle_in_renderer; |
137 // below is safe. | 179 DuplicateHandle(base::GetCurrentProcessHandle(), |
138 DCHECK(sizeof(HANDLE) == sizeof(imc_handle)); | 180 reinterpret_cast<HANDLE>(sockets_for_renderer_[i]), |
139 DuplicateHandle(base::GetCurrentProcessHandle(), | 181 resource_message_filter_->handle(), |
140 reinterpret_cast<HANDLE>(pair_[0]), | 182 &handle_in_renderer, |
141 resource_message_filter_->handle(), | 183 GENERIC_READ | GENERIC_WRITE, |
142 reinterpret_cast<HANDLE*>(&imc_handle), | 184 FALSE, |
143 GENERIC_READ | GENERIC_WRITE, | 185 DUPLICATE_CLOSE_SOURCE); |
144 FALSE, | 186 handles_for_renderer.push_back( |
145 DUPLICATE_CLOSE_SOURCE); | 187 reinterpret_cast<nacl::FileDescriptor>(handle_in_renderer)); |
| 188 #else |
| 189 // No need to dup the imc_handle - we don't pass it anywhere else so |
| 190 // it cannot be closed. |
| 191 nacl::FileDescriptor imc_handle; |
| 192 imc_handle.fd = sockets_for_renderer_[i]; |
| 193 imc_handle.auto_close = true; |
| 194 handles_for_renderer.push_back(imc_handle); |
| 195 #endif |
| 196 } |
146 | 197 |
147 // Duplicate the process handle | 198 #if defined(OS_WIN) |
| 199 // Copy the process handle into the renderer process. |
148 DuplicateHandle(base::GetCurrentProcessHandle(), | 200 DuplicateHandle(base::GetCurrentProcessHandle(), |
149 handle(), | 201 handle(), |
150 resource_message_filter_->handle(), | 202 resource_message_filter_->handle(), |
151 &nacl_process_handle, | 203 &nacl_process_handle, |
152 PROCESS_DUP_HANDLE, | 204 PROCESS_DUP_HANDLE, |
153 FALSE, | 205 FALSE, |
154 0); | 206 0); |
155 #else | 207 #else |
156 int flags = fcntl(pair_[0], F_GETFD); | |
157 if (flags != -1) { | |
158 flags |= FD_CLOEXEC; | |
159 fcntl(pair_[0], F_SETFD, flags); | |
160 } | |
161 // No need to dup the imc_handle - we don't pass it anywhere else so | |
162 // it cannot be closed. | |
163 imc_handle.fd = pair_[0]; | |
164 imc_handle.auto_close = true; | |
165 | |
166 // We use pid as process handle on Posix | 208 // We use pid as process handle on Posix |
167 nacl_process_handle = handle(); | 209 nacl_process_handle = handle(); |
168 #endif | 210 #endif |
169 | 211 |
170 // Get the pid of the NaCl process | 212 // Get the pid of the NaCl process |
171 base::ProcessId nacl_process_id = base::GetProcId(handle()); | 213 base::ProcessId nacl_process_id = base::GetProcId(handle()); |
172 | 214 |
173 ViewHostMsg_LaunchNaCl::WriteReplyParams( | 215 ViewHostMsg_LaunchNaCl::WriteReplyParams( |
174 reply_msg_, imc_handle, nacl_process_handle, nacl_process_id); | 216 reply_msg_, handles_for_renderer, nacl_process_handle, nacl_process_id); |
175 resource_message_filter_->Send(reply_msg_); | 217 resource_message_filter_->Send(reply_msg_); |
176 resource_message_filter_ = NULL; | 218 resource_message_filter_ = NULL; |
177 reply_msg_ = NULL; | 219 reply_msg_ = NULL; |
| 220 sockets_for_renderer_.clear(); |
178 | 221 |
179 SendStartMessage(); | 222 SendStartMessage(); |
180 } | 223 } |
181 | 224 |
182 void NaClProcessHost::SendStartMessage() { | 225 void NaClProcessHost::SendStartMessage() { |
183 nacl::FileDescriptor channel; | 226 std::vector<nacl::FileDescriptor> handles_for_sel_ldr; |
| 227 for (size_t i = 0; i < sockets_for_sel_ldr_.size(); i++) { |
184 #if defined(OS_WIN) | 228 #if defined(OS_WIN) |
185 if (!DuplicateHandle(GetCurrentProcess(), | 229 HANDLE channel; |
186 reinterpret_cast<HANDLE>(pair_[1]), | 230 if (!DuplicateHandle(GetCurrentProcess(), |
187 handle(), | 231 reinterpret_cast<HANDLE>(sockets_for_sel_ldr_[i]), |
188 reinterpret_cast<HANDLE*>(&channel), | 232 handle(), |
189 GENERIC_READ | GENERIC_WRITE, | 233 &channel, |
190 FALSE, DUPLICATE_CLOSE_SOURCE)) { | 234 GENERIC_READ | GENERIC_WRITE, |
191 return; | 235 FALSE, DUPLICATE_CLOSE_SOURCE)) { |
| 236 return; |
| 237 } |
| 238 handles_for_sel_ldr.push_back( |
| 239 reinterpret_cast<nacl::FileDescriptor>(channel)); |
| 240 #else |
| 241 nacl::FileDescriptor channel; |
| 242 channel.fd = dup(sockets_for_sel_ldr_[i]); |
| 243 channel.auto_close = true; |
| 244 handles_for_sel_ldr.push_back(channel); |
| 245 #endif |
192 } | 246 } |
193 #else | 247 |
194 channel.fd = dup(pair_[1]); | 248 Send(new NaClProcessMsg_Start(handles_for_sel_ldr)); |
195 channel.auto_close = true; | 249 sockets_for_sel_ldr_.clear(); |
196 #endif | |
197 Send(new NaClProcessMsg_Start(descriptor_, channel)); | |
198 } | 250 } |
199 | 251 |
200 void NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { | 252 void NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { |
201 NOTREACHED() << "Invalid message with type = " << msg.type(); | 253 NOTREACHED() << "Invalid message with type = " << msg.type(); |
202 } | 254 } |
203 | 255 |
204 URLRequestContext* NaClProcessHost::GetRequestContext( | 256 URLRequestContext* NaClProcessHost::GetRequestContext( |
205 uint32 request_id, | 257 uint32 request_id, |
206 const ViewHostMsg_Resource_Request& request_data) { | 258 const ViewHostMsg_Resource_Request& request_data) { |
207 return NULL; | 259 return NULL; |
(...skipping 12 matching lines...) Expand all Loading... |
220 if (fnIsWow64Process != NULL) { | 272 if (fnIsWow64Process != NULL) { |
221 BOOL bIsWow64 = FALSE; | 273 BOOL bIsWow64 = FALSE; |
222 if (fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) { | 274 if (fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) { |
223 if (bIsWow64) { | 275 if (bIsWow64) { |
224 running_on_wow64_ = true; | 276 running_on_wow64_ = true; |
225 } | 277 } |
226 } | 278 } |
227 } | 279 } |
228 } | 280 } |
229 #endif | 281 #endif |
OLD | NEW |