| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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> |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 #endif | 33 #endif |
| 34 | 34 |
| 35 using content::BrowserThread; | 35 using content::BrowserThread; |
| 36 | 36 |
| 37 namespace { | 37 namespace { |
| 38 | 38 |
| 39 #if !defined(DISABLE_NACL) | 39 #if !defined(DISABLE_NACL) |
| 40 void SetCloseOnExec(nacl::Handle fd) { | 40 void SetCloseOnExec(nacl::Handle fd) { |
| 41 #if defined(OS_POSIX) | 41 #if defined(OS_POSIX) |
| 42 int flags = fcntl(fd, F_GETFD); | 42 int flags = fcntl(fd, F_GETFD); |
| 43 CHECK(flags != -1); | 43 CHECK_NE(flags, -1); |
| 44 int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC); | 44 int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC); |
| 45 CHECK(rc == 0); | 45 CHECK_EQ(rc, 0); |
| 46 #endif | 46 #endif |
| 47 } | 47 } |
| 48 #endif | 48 #endif |
| 49 | 49 |
| 50 // Represents shared state for all NaClProcessHost objects in the browser. |
| 51 // Currently this just handles holding onto the file descriptor for the IRT. |
| 52 class NaClBrowser { |
| 53 public: |
| 54 static NaClBrowser* GetInstance() { |
| 55 return Singleton<NaClBrowser>::get(); |
| 56 } |
| 57 |
| 58 bool IrtAvailable() const { |
| 59 return irt_platform_file_ != base::kInvalidPlatformFileValue; |
| 60 } |
| 61 |
| 62 base::PlatformFile IrtFile() const { |
| 63 CHECK_NE(irt_platform_file_, base::kInvalidPlatformFileValue); |
| 64 return irt_platform_file_; |
| 65 } |
| 66 |
| 67 // Asynchronously attempt to get the IRT open. |
| 68 bool EnsureIrtAvailable(); |
| 69 |
| 70 // Make sure the IRT gets opened and follow up with the reply when it's ready. |
| 71 bool MakeIrtAvailable(const base::Closure& reply); |
| 72 |
| 73 private: |
| 74 base::PlatformFile irt_platform_file_; |
| 75 |
| 76 friend struct DefaultSingletonTraits<NaClBrowser>; |
| 77 |
| 78 NaClBrowser() |
| 79 : irt_platform_file_(base::kInvalidPlatformFileValue) |
| 80 {} |
| 81 |
| 82 ~NaClBrowser() { |
| 83 if (irt_platform_file_ != base::kInvalidPlatformFileValue) |
| 84 base::ClosePlatformFile(irt_platform_file_); |
| 85 } |
| 86 |
| 87 void OpenIrtLibraryFile(); |
| 88 |
| 89 static void DoOpenIrtLibraryFile() { |
| 90 GetInstance()->OpenIrtLibraryFile(); |
| 91 } |
| 92 |
| 93 DISALLOW_COPY_AND_ASSIGN(NaClBrowser); |
| 94 }; |
| 95 |
| 50 } // namespace | 96 } // namespace |
| 51 | 97 |
| 52 struct NaClProcessHost::NaClInternal { | 98 struct NaClProcessHost::NaClInternal { |
| 53 std::vector<nacl::Handle> sockets_for_renderer; | 99 std::vector<nacl::Handle> sockets_for_renderer; |
| 54 std::vector<nacl::Handle> sockets_for_sel_ldr; | 100 std::vector<nacl::Handle> sockets_for_sel_ldr; |
| 55 }; | 101 }; |
| 56 | 102 |
| 103 static bool RunningOnWOW64() { |
| 104 #if defined(OS_WIN) |
| 105 return (base::win::OSInfo::GetInstance()->wow64_status() == |
| 106 base::win::OSInfo::WOW64_ENABLED); |
| 107 #else |
| 108 return false; |
| 109 #endif |
| 110 } |
| 111 |
| 57 NaClProcessHost::NaClProcessHost(const std::wstring& url) | 112 NaClProcessHost::NaClProcessHost(const std::wstring& url) |
| 58 : BrowserChildProcessHost(NACL_LOADER_PROCESS), | 113 : BrowserChildProcessHost(NACL_LOADER_PROCESS), |
| 59 reply_msg_(NULL), | 114 reply_msg_(NULL), |
| 60 internal_(new NaClInternal()), | 115 internal_(new NaClInternal()), |
| 61 running_on_wow64_(false), | |
| 62 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | 116 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
| 63 set_name(WideToUTF16Hack(url)); | 117 set_name(WideToUTF16Hack(url)); |
| 64 #if defined(OS_WIN) | |
| 65 running_on_wow64_ = (base::win::OSInfo::GetInstance()->wow64_status() == | |
| 66 base::win::OSInfo::WOW64_ENABLED); | |
| 67 #endif | |
| 68 } | 118 } |
| 69 | 119 |
| 70 NaClProcessHost::~NaClProcessHost() { | 120 NaClProcessHost::~NaClProcessHost() { |
| 71 // nacl::Close() is not available at link time if DISABLE_NACL is | 121 // nacl::Close() is not available at link time if DISABLE_NACL is |
| 72 // defined, but we still compile a bunch of other code from this | 122 // defined, but we still compile a bunch of other code from this |
| 73 // file anyway. TODO(mseaborn): Make this less messy. | 123 // file anyway. TODO(mseaborn): Make this less messy. |
| 74 #ifndef DISABLE_NACL | 124 #ifndef DISABLE_NACL |
| 75 for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { | 125 for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { |
| 76 if (nacl::Close(internal_->sockets_for_renderer[i]) != 0) { | 126 if (nacl::Close(internal_->sockets_for_renderer[i]) != 0) { |
| 77 LOG(ERROR) << "nacl::Close() failed"; | 127 LOG(ERROR) << "nacl::Close() failed"; |
| 78 } | 128 } |
| 79 } | 129 } |
| 80 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { | 130 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { |
| 81 if (nacl::Close(internal_->sockets_for_sel_ldr[i]) != 0) { | 131 if (nacl::Close(internal_->sockets_for_sel_ldr[i]) != 0) { |
| 82 LOG(ERROR) << "nacl::Close() failed"; | 132 LOG(ERROR) << "nacl::Close() failed"; |
| 83 } | 133 } |
| 84 } | 134 } |
| 85 #endif | 135 #endif |
| 86 | 136 |
| 87 if (reply_msg_) { | 137 if (reply_msg_) { |
| 88 // The process failed to launch for some reason. | 138 // The process failed to launch for some reason. |
| 89 // Don't keep the renderer hanging. | 139 // Don't keep the renderer hanging. |
| 90 reply_msg_->set_reply_error(); | 140 reply_msg_->set_reply_error(); |
| 91 chrome_render_message_filter_->Send(reply_msg_); | 141 chrome_render_message_filter_->Send(reply_msg_); |
| 92 } | 142 } |
| 93 } | 143 } |
| 94 | 144 |
| 145 // Attempt to ensure the IRT will be available when we need it, but don't wait. |
| 146 bool NaClBrowser::EnsureIrtAvailable() { |
| 147 if (IrtAvailable()) |
| 148 return true; |
| 149 |
| 150 return BrowserThread::PostTask( |
| 151 BrowserThread::FILE, FROM_HERE, |
| 152 base::Bind(&NaClBrowser::DoOpenIrtLibraryFile)); |
| 153 } |
| 154 |
| 155 // We really need the IRT to be available now, so make sure that it is. |
| 156 // When it's ready, we'll run the reply closure. |
| 157 bool NaClBrowser::MakeIrtAvailable(const base::Closure& reply) { |
| 158 return BrowserThread::PostTaskAndReply( |
| 159 BrowserThread::FILE, FROM_HERE, |
| 160 base::Bind(&NaClBrowser::DoOpenIrtLibraryFile), reply); |
| 161 } |
| 162 |
| 163 // This is called at browser startup. |
| 164 // static |
| 165 void NaClProcessHost::EarlyStartup() { |
| 166 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 167 // Open the IRT file early to make sure that it isn't replaced out from |
| 168 // under us by autoupdate. |
| 169 NaClBrowser::GetInstance()->EnsureIrtAvailable(); |
| 170 #endif |
| 171 } |
| 172 |
| 95 bool NaClProcessHost::Launch( | 173 bool NaClProcessHost::Launch( |
| 96 ChromeRenderMessageFilter* chrome_render_message_filter, | 174 ChromeRenderMessageFilter* chrome_render_message_filter, |
| 97 int socket_count, | 175 int socket_count, |
| 98 IPC::Message* reply_msg) { | 176 IPC::Message* reply_msg) { |
| 99 #ifdef DISABLE_NACL | 177 #ifdef DISABLE_NACL |
| 100 NOTIMPLEMENTED() << "Native Client disabled at build time"; | 178 NOTIMPLEMENTED() << "Native Client disabled at build time"; |
| 101 return false; | 179 return false; |
| 102 #else | 180 #else |
| 103 // Place an arbitrary limit on the number of sockets to limit | 181 // Place an arbitrary limit on the number of sockets to limit |
| 104 // exposure in case the renderer is compromised. We can increase | 182 // exposure in case the renderer is compromised. We can increase |
| 105 // this if necessary. | 183 // this if necessary. |
| 106 if (socket_count > 8) { | 184 if (socket_count > 8) { |
| 107 return false; | 185 return false; |
| 108 } | 186 } |
| 109 | 187 |
| 188 // Start getting the IRT open asynchronously while we launch the NaCl process. |
| 189 // We'll make sure this actually finished in OnProcessLaunched, below. |
| 190 if (!NaClBrowser::GetInstance()->EnsureIrtAvailable()) { |
| 191 LOG(ERROR) << "Cannot launch NaCl process after IRT file open failed"; |
| 192 return false; |
| 193 } |
| 194 |
| 110 // Rather than creating a socket pair in the renderer, and passing | 195 // Rather than creating a socket pair in the renderer, and passing |
| 111 // one side through the browser to sel_ldr, socket pairs are created | 196 // one side through the browser to sel_ldr, socket pairs are created |
| 112 // in the browser and then passed to the renderer and sel_ldr. | 197 // in the browser and then passed to the renderer and sel_ldr. |
| 113 // | 198 // |
| 114 // This is mainly for the benefit of Windows, where sockets cannot | 199 // This is mainly for the benefit of Windows, where sockets cannot |
| 115 // be passed in messages, but are copied via DuplicateHandle(). | 200 // be passed in messages, but are copied via DuplicateHandle(). |
| 116 // This means the sandboxed renderer cannot send handles to the | 201 // This means the sandboxed renderer cannot send handles to the |
| 117 // browser process. | 202 // browser process. |
| 118 | 203 |
| 119 for (int i = 0; i < socket_count; i++) { | 204 for (int i = 0; i < socket_count; i++) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 switches::kNaClLoaderProcess); | 260 switches::kNaClLoaderProcess); |
| 176 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id()); | 261 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id()); |
| 177 if (logging::DialogsAreSuppressed()) | 262 if (logging::DialogsAreSuppressed()) |
| 178 cmd_line->AppendSwitch(switches::kNoErrorDialogs); | 263 cmd_line->AppendSwitch(switches::kNoErrorDialogs); |
| 179 | 264 |
| 180 if (!nacl_loader_prefix.empty()) | 265 if (!nacl_loader_prefix.empty()) |
| 181 cmd_line->PrependWrapper(nacl_loader_prefix); | 266 cmd_line->PrependWrapper(nacl_loader_prefix); |
| 182 | 267 |
| 183 // On Windows we might need to start the broker process to launch a new loader | 268 // On Windows we might need to start the broker process to launch a new loader |
| 184 #if defined(OS_WIN) | 269 #if defined(OS_WIN) |
| 185 if (running_on_wow64_) { | 270 if (RunningOnWOW64()) { |
| 186 return NaClBrokerService::GetInstance()->LaunchLoader( | 271 return NaClBrokerService::GetInstance()->LaunchLoader( |
| 187 this, ASCIIToWide(channel_id())); | 272 this, ASCIIToWide(channel_id())); |
| 188 } else { | 273 } else { |
| 189 BrowserChildProcessHost::Launch(FilePath(), cmd_line); | 274 BrowserChildProcessHost::Launch(FilePath(), cmd_line); |
| 190 } | 275 } |
| 191 #elif defined(OS_POSIX) | 276 #elif defined(OS_POSIX) |
| 192 BrowserChildProcessHost::Launch(nacl_loader_prefix.empty(), // use_zygote | 277 BrowserChildProcessHost::Launch(nacl_loader_prefix.empty(), // use_zygote |
| 193 base::environment_vector(), | 278 base::environment_vector(), |
| 194 cmd_line); | 279 cmd_line); |
| 195 #endif | 280 #endif |
| 196 | 281 |
| 197 return true; | 282 return true; |
| 198 } | 283 } |
| 199 | 284 |
| 200 void NaClProcessHost::OnProcessLaunchedByBroker(base::ProcessHandle handle) { | 285 void NaClProcessHost::OnProcessLaunchedByBroker(base::ProcessHandle handle) { |
| 201 set_handle(handle); | 286 set_handle(handle); |
| 202 OnProcessLaunched(); | 287 OnProcessLaunched(); |
| 203 } | 288 } |
| 204 | 289 |
| 205 base::TerminationStatus NaClProcessHost::GetChildTerminationStatus( | 290 base::TerminationStatus NaClProcessHost::GetChildTerminationStatus( |
| 206 int* exit_code) { | 291 int* exit_code) { |
| 207 if (running_on_wow64_) | 292 if (RunningOnWOW64()) |
| 208 return base::GetTerminationStatus(handle(), exit_code); | 293 return base::GetTerminationStatus(handle(), exit_code); |
| 209 return BrowserChildProcessHost::GetChildTerminationStatus(exit_code); | 294 return BrowserChildProcessHost::GetChildTerminationStatus(exit_code); |
| 210 } | 295 } |
| 211 | 296 |
| 212 void NaClProcessHost::OnChildDied() { | 297 void NaClProcessHost::OnChildDied() { |
| 213 int exit_code; | 298 int exit_code; |
| 214 GetChildTerminationStatus(&exit_code); | 299 GetChildTerminationStatus(&exit_code); |
| 215 std::string message = | 300 std::string message = |
| 216 base::StringPrintf("NaCl process exited with status %i (0x%x)", | 301 base::StringPrintf("NaCl process exited with status %i (0x%x)", |
| 217 exit_code, exit_code); | 302 exit_code, exit_code); |
| 218 if (exit_code == 0) { | 303 if (exit_code == 0) { |
| 219 LOG(INFO) << message; | 304 LOG(INFO) << message; |
| 220 } else { | 305 } else { |
| 221 LOG(ERROR) << message; | 306 LOG(ERROR) << message; |
| 222 } | 307 } |
| 223 | 308 |
| 224 #if defined(OS_WIN) | 309 #if defined(OS_WIN) |
| 225 NaClBrokerService::GetInstance()->OnLoaderDied(); | 310 NaClBrokerService::GetInstance()->OnLoaderDied(); |
| 226 #endif | 311 #endif |
| 227 BrowserChildProcessHost::OnChildDied(); | 312 BrowserChildProcessHost::OnChildDied(); |
| 228 } | 313 } |
| 229 | 314 |
| 230 FilePath::StringType NaClProcessHost::GetIrtLibraryFilename() { | 315 // This only ever runs on the BrowserThread::FILE thread. |
| 231 bool on_x86_64 = running_on_wow64_; | 316 // If multiple tasks are posted, the later ones are no-ops. |
| 232 #if defined(__x86_64__) | 317 void NaClBrowser::OpenIrtLibraryFile() { |
| 233 on_x86_64 = true; | 318 if (irt_platform_file_ != base::kInvalidPlatformFileValue) |
| 234 #endif | 319 // We've already run. |
| 235 if (on_x86_64) { | 320 return; |
| 236 return FILE_PATH_LITERAL("nacl_irt_x86_64.nexe"); | |
| 237 } else { | |
| 238 return FILE_PATH_LITERAL("nacl_irt_x86_32.nexe"); | |
| 239 } | |
| 240 } | |
| 241 | 321 |
| 242 void NaClProcessHost::OnProcessLaunched() { | 322 FilePath irt_filepath; |
| 243 // TODO(mseaborn): Opening the IRT file every time a NaCl process is | 323 |
| 244 // launched probably does not work with auto-update on Linux. We | |
| 245 // might need to open the file on startup. If so, we would need to | |
| 246 // ensure that NaCl's ELF loader does not use lseek() on the shared | |
| 247 // IRT file descriptor, otherwise there would be a race condition. | |
| 248 FilePath irt_path; | |
| 249 // Allow the IRT library to be overridden via an environment | 324 // Allow the IRT library to be overridden via an environment |
| 250 // variable. This allows the NaCl/Chromium integration bot to | 325 // variable. This allows the NaCl/Chromium integration bot to |
| 251 // specify a newly-built IRT rather than using a prebuilt one | 326 // specify a newly-built IRT rather than using a prebuilt one |
| 252 // downloaded via Chromium's DEPS file. We use the same environment | 327 // downloaded via Chromium's DEPS file. We use the same environment |
| 253 // variable that the standalone NaCl PPAPI plugin accepts. | 328 // variable that the standalone NaCl PPAPI plugin accepts. |
| 254 const char* irt_path_var = getenv("NACL_IRT_LIBRARY"); | 329 const char* irt_path_var = getenv("NACL_IRT_LIBRARY"); |
| 255 if (irt_path_var != NULL) { | 330 if (irt_path_var != NULL) { |
| 256 FilePath::StringType string(irt_path_var, | 331 FilePath::StringType path_string( |
| 257 irt_path_var + strlen(irt_path_var)); | 332 irt_path_var, const_cast<const char*>(strchr(irt_path_var, '\0'))); |
| 258 irt_path = FilePath(string); | 333 irt_filepath = FilePath(path_string); |
| 259 } else { | 334 } else { |
| 260 FilePath plugin_dir; | 335 FilePath plugin_dir; |
| 261 if (!PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &plugin_dir)) { | 336 if (!PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &plugin_dir)) { |
| 262 LOG(ERROR) << "Failed to locate the plugins directory"; | 337 LOG(ERROR) << "Failed to locate the plugins directory"; |
| 263 delete this; | |
| 264 return; | 338 return; |
| 265 } | 339 } |
| 266 irt_path = plugin_dir.Append(GetIrtLibraryFilename()); | 340 |
| 341 bool on_x86_64 = RunningOnWOW64(); |
| 342 #if defined(__x86_64__) |
| 343 on_x86_64 = true; |
| 344 #endif |
| 345 FilePath::StringType irt_name; |
| 346 if (on_x86_64) { |
| 347 irt_name = FILE_PATH_LITERAL("nacl_irt_x86_64.nexe"); |
| 348 } else { |
| 349 irt_name = FILE_PATH_LITERAL("nacl_irt_x86_32.nexe"); |
| 350 } |
| 351 |
| 352 irt_filepath = plugin_dir.Append(irt_name); |
| 267 } | 353 } |
| 268 | 354 |
| 269 if (!base::FileUtilProxy::CreateOrOpen( | 355 base::PlatformFileError error_code; |
| 270 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), | 356 irt_platform_file_ = base::CreatePlatformFile(irt_filepath, |
| 271 irt_path, | 357 base::PLATFORM_FILE_OPEN | |
| 272 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, | 358 base::PLATFORM_FILE_READ, |
| 273 base::Bind(&NaClProcessHost::OpenIrtFileDone, | 359 NULL, |
| 274 weak_factory_.GetWeakPtr()))) { | 360 &error_code); |
| 361 if (error_code != base::PLATFORM_FILE_OK) { |
| 362 LOG(ERROR) << "Failed to open NaCl IRT file \"" |
| 363 << irt_filepath.LossyDisplayName() |
| 364 << "\": " << error_code; |
| 365 } |
| 366 } |
| 367 |
| 368 void NaClProcessHost::OnProcessLaunched() { |
| 369 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
| 370 |
| 371 if (nacl_browser->IrtAvailable()) { |
| 372 // The IRT is already open. Away we go. |
| 373 SendStart(nacl_browser->IrtFile()); |
| 374 } else { |
| 375 // We're waiting for the IRT to be open. |
| 376 nacl_browser->MakeIrtAvailable(base::Bind(&NaClProcessHost::IrtReady, |
| 377 weak_factory_.GetWeakPtr())); |
| 378 } |
| 379 } |
| 380 |
| 381 // The asynchronous attempt to get the IRT file open has completed. |
| 382 void NaClProcessHost::IrtReady() { |
| 383 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
| 384 |
| 385 if (nacl_browser->IrtAvailable()) { |
| 386 SendStart(nacl_browser->IrtFile()); |
| 387 } else { |
| 388 LOG(ERROR) << "Cannot launch NaCl process after IRT file open failed"; |
| 275 delete this; | 389 delete this; |
| 276 } | 390 } |
| 277 } | 391 } |
| 278 | 392 |
| 279 void NaClProcessHost::OpenIrtFileDone(base::PlatformFileError error_code, | 393 static bool SendHandleToSelLdr( |
| 280 base::PassPlatformFile file, | 394 base::ProcessHandle processh, |
| 281 bool created) { | 395 nacl::Handle sourceh, bool close_source, |
| 396 std::vector<nacl::FileDescriptor> *handles_for_sel_ldr) { |
| 397 #if defined(OS_WIN) |
| 398 HANDLE channel; |
| 399 int flags = DUPLICATE_SAME_ACCESS; |
| 400 if (close_source) |
| 401 flags |= DUPLICATE_CLOSE_SOURCE; |
| 402 if (!DuplicateHandle(GetCurrentProcess(), |
| 403 reinterpret_cast<HANDLE>(sourceh), |
| 404 processh, |
| 405 &channel, |
| 406 0, // Unused given DUPLICATE_SAME_ACCESS. |
| 407 FALSE, |
| 408 flags)) { |
| 409 LOG(ERROR) << "DuplicateHandle() failed"; |
| 410 return false; |
| 411 } |
| 412 handles_for_sel_ldr->push_back( |
| 413 reinterpret_cast<nacl::FileDescriptor>(channel)); |
| 414 #else |
| 415 nacl::FileDescriptor channel; |
| 416 channel.fd = sourceh; |
| 417 channel.auto_close = close_source; |
| 418 handles_for_sel_ldr->push_back(channel); |
| 419 #endif |
| 420 return true; |
| 421 } |
| 422 |
| 423 void NaClProcessHost::SendStart(base::PlatformFile irt_file) { |
| 424 CHECK_NE(irt_file, base::kInvalidPlatformFileValue); |
| 425 |
| 282 std::vector<nacl::FileDescriptor> handles_for_renderer; | 426 std::vector<nacl::FileDescriptor> handles_for_renderer; |
| 283 base::ProcessHandle nacl_process_handle; | 427 base::ProcessHandle nacl_process_handle; |
| 284 bool have_irt_file = false; | |
| 285 if (base::PLATFORM_FILE_OK == error_code) { | |
| 286 internal_->sockets_for_sel_ldr.push_back(file.ReleaseValue()); | |
| 287 have_irt_file = true; | |
| 288 } else { | |
| 289 LOG(ERROR) << "Failed to open the NaCl IRT library file"; | |
| 290 } | |
| 291 | 428 |
| 292 for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { | 429 for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { |
| 293 #if defined(OS_WIN) | 430 #if defined(OS_WIN) |
| 294 // Copy the handle into the renderer process. | 431 // Copy the handle into the renderer process. |
| 295 HANDLE handle_in_renderer; | 432 HANDLE handle_in_renderer; |
| 296 if (!DuplicateHandle(base::GetCurrentProcessHandle(), | 433 if (!DuplicateHandle(base::GetCurrentProcessHandle(), |
| 297 reinterpret_cast<HANDLE>( | 434 reinterpret_cast<HANDLE>( |
| 298 internal_->sockets_for_renderer[i]), | 435 internal_->sockets_for_renderer[i]), |
| 299 chrome_render_message_filter_->peer_handle(), | 436 chrome_render_message_filter_->peer_handle(), |
| 300 &handle_in_renderer, | 437 &handle_in_renderer, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 | 477 |
| 341 ChromeViewHostMsg_LaunchNaCl::WriteReplyParams( | 478 ChromeViewHostMsg_LaunchNaCl::WriteReplyParams( |
| 342 reply_msg_, handles_for_renderer, nacl_process_handle, nacl_process_id); | 479 reply_msg_, handles_for_renderer, nacl_process_handle, nacl_process_id); |
| 343 chrome_render_message_filter_->Send(reply_msg_); | 480 chrome_render_message_filter_->Send(reply_msg_); |
| 344 chrome_render_message_filter_ = NULL; | 481 chrome_render_message_filter_ = NULL; |
| 345 reply_msg_ = NULL; | 482 reply_msg_ = NULL; |
| 346 internal_->sockets_for_renderer.clear(); | 483 internal_->sockets_for_renderer.clear(); |
| 347 | 484 |
| 348 std::vector<nacl::FileDescriptor> handles_for_sel_ldr; | 485 std::vector<nacl::FileDescriptor> handles_for_sel_ldr; |
| 349 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { | 486 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { |
| 350 #if defined(OS_WIN) | 487 if (!SendHandleToSelLdr(handle(), |
| 351 HANDLE channel; | 488 internal_->sockets_for_sel_ldr[i], true, |
| 352 if (!DuplicateHandle(GetCurrentProcess(), | 489 &handles_for_sel_ldr)) { |
| 353 reinterpret_cast<HANDLE>( | |
| 354 internal_->sockets_for_sel_ldr[i]), | |
| 355 handle(), | |
| 356 &channel, | |
| 357 0, // Unused given DUPLICATE_SAME_ACCESS. | |
| 358 FALSE, | |
| 359 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { | |
| 360 LOG(ERROR) << "DuplicateHandle() failed"; | |
| 361 delete this; | 490 delete this; |
| 362 return; | 491 return; |
| 363 } | 492 } |
| 364 handles_for_sel_ldr.push_back( | 493 } |
| 365 reinterpret_cast<nacl::FileDescriptor>(channel)); | 494 |
| 366 #else | 495 // Send over the IRT file handle. We don't close our own copy! |
| 367 nacl::FileDescriptor channel; | 496 if (!SendHandleToSelLdr(handle(), irt_file, false, &handles_for_sel_ldr)) { |
| 368 channel.fd = internal_->sockets_for_sel_ldr[i]; | 497 delete this; |
| 369 channel.auto_close = true; | 498 return; |
| 370 handles_for_sel_ldr.push_back(channel); | |
| 371 #endif | |
| 372 } | 499 } |
| 373 | 500 |
| 374 #if defined(OS_MACOSX) | 501 #if defined(OS_MACOSX) |
| 375 // For dynamic loading support, NaCl requires a file descriptor that | 502 // For dynamic loading support, NaCl requires a file descriptor that |
| 376 // was created in /tmp, since those created with shm_open() are not | 503 // was created in /tmp, since those created with shm_open() are not |
| 377 // mappable with PROT_EXEC. Rather than requiring an extra IPC | 504 // mappable with PROT_EXEC. Rather than requiring an extra IPC |
| 378 // round trip out of the sandbox, we create an FD here. | 505 // round trip out of the sandbox, we create an FD here. |
| 379 base::SharedMemory memory_buffer; | 506 base::SharedMemory memory_buffer; |
| 380 if (!memory_buffer.CreateAnonymous(/* size= */ 1)) { | 507 if (!memory_buffer.CreateAnonymous(/* size= */ 1)) { |
| 381 LOG(ERROR) << "Failed to allocate memory buffer"; | 508 LOG(ERROR) << "Failed to allocate memory buffer"; |
| 382 delete this; | 509 delete this; |
| 383 return; | 510 return; |
| 384 } | 511 } |
| 385 nacl::FileDescriptor memory_fd; | 512 nacl::FileDescriptor memory_fd; |
| 386 memory_fd.fd = dup(memory_buffer.handle().fd); | 513 memory_fd.fd = dup(memory_buffer.handle().fd); |
| 387 if (memory_fd.fd < 0) { | 514 if (memory_fd.fd < 0) { |
| 388 LOG(ERROR) << "Failed to dup() a file descriptor"; | 515 LOG(ERROR) << "Failed to dup() a file descriptor"; |
| 389 delete this; | 516 delete this; |
| 390 return; | 517 return; |
| 391 } | 518 } |
| 392 memory_fd.auto_close = true; | 519 memory_fd.auto_close = true; |
| 393 handles_for_sel_ldr.push_back(memory_fd); | 520 handles_for_sel_ldr.push_back(memory_fd); |
| 394 #endif | 521 #endif |
| 395 | 522 |
| 396 Send(new NaClProcessMsg_Start(handles_for_sel_ldr, have_irt_file)); | 523 Send(new NaClProcessMsg_Start(handles_for_sel_ldr)); |
| 397 internal_->sockets_for_sel_ldr.clear(); | 524 internal_->sockets_for_sel_ldr.clear(); |
| 398 } | 525 } |
| 399 | 526 |
| 400 bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { | 527 bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { |
| 401 NOTREACHED() << "Invalid message with type = " << msg.type(); | 528 NOTREACHED() << "Invalid message with type = " << msg.type(); |
| 402 return false; | 529 return false; |
| 403 } | 530 } |
| 404 | 531 |
| 405 bool NaClProcessHost::CanShutdown() { | 532 bool NaClProcessHost::CanShutdown() { |
| 406 return true; | 533 return true; |
| 407 } | 534 } |
| OLD | NEW |