| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/nacl/nacl_broker_listener.h" | |
| 6 | |
| 7 #include "base/base_switches.h" | |
| 8 #include "base/bind.h" | |
| 9 #include "base/command_line.h" | |
| 10 #include "base/message_loop.h" | |
| 11 #include "base/message_loop/message_loop_proxy.h" | |
| 12 #include "base/path_service.h" | |
| 13 #include "base/process_util.h" | |
| 14 #include "chrome/common/chrome_switches.h" | |
| 15 #include "chrome/common/nacl_cmd_line.h" | |
| 16 #include "chrome/common/nacl_debug_exception_handler_win.h" | |
| 17 #include "chrome/common/nacl_messages.h" | |
| 18 #include "components/nacl/common/nacl_switches.h" | |
| 19 #include "content/public/common/content_switches.h" | |
| 20 #include "content/public/common/sandbox_init.h" | |
| 21 #include "ipc/ipc_channel.h" | |
| 22 #include "ipc/ipc_switches.h" | |
| 23 #include "sandbox/win/src/sandbox_policy.h" | |
| 24 | |
| 25 namespace { | |
| 26 | |
| 27 void SendReply(IPC::Channel* channel, int32 pid, bool result) { | |
| 28 channel->Send(new NaClProcessMsg_DebugExceptionHandlerLaunched(pid, result)); | |
| 29 } | |
| 30 | |
| 31 } // namespace | |
| 32 | |
| 33 NaClBrokerListener::NaClBrokerListener() | |
| 34 : browser_handle_(base::kNullProcessHandle) { | |
| 35 } | |
| 36 | |
| 37 NaClBrokerListener::~NaClBrokerListener() { | |
| 38 base::CloseProcessHandle(browser_handle_); | |
| 39 } | |
| 40 | |
| 41 void NaClBrokerListener::Listen() { | |
| 42 std::string channel_name = | |
| 43 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
| 44 switches::kProcessChannelID); | |
| 45 channel_.reset(new IPC::Channel( | |
| 46 channel_name, IPC::Channel::MODE_CLIENT, this)); | |
| 47 CHECK(channel_->Connect()); | |
| 48 base::MessageLoop::current()->Run(); | |
| 49 } | |
| 50 | |
| 51 // NOTE: changes to this method need to be reviewed by the security team. | |
| 52 void NaClBrokerListener::PreSpawnTarget(sandbox::TargetPolicy* policy, | |
| 53 bool* success) { | |
| 54 // This code is duplicated in chrome_content_browser_client.cc. | |
| 55 | |
| 56 // Allow the server side of a pipe restricted to the "chrome.nacl." | |
| 57 // namespace so that it cannot impersonate other system or other chrome | |
| 58 // service pipes. | |
| 59 sandbox::ResultCode result = policy->AddRule( | |
| 60 sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, | |
| 61 sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, | |
| 62 L"\\\\.\\pipe\\chrome.nacl.*"); | |
| 63 *success = (result == sandbox::SBOX_ALL_OK); | |
| 64 } | |
| 65 | |
| 66 void NaClBrokerListener::OnChannelConnected(int32 peer_pid) { | |
| 67 bool res = base::OpenPrivilegedProcessHandle(peer_pid, &browser_handle_); | |
| 68 CHECK(res); | |
| 69 } | |
| 70 | |
| 71 bool NaClBrokerListener::OnMessageReceived(const IPC::Message& msg) { | |
| 72 bool handled = true; | |
| 73 IPC_BEGIN_MESSAGE_MAP(NaClBrokerListener, msg) | |
| 74 IPC_MESSAGE_HANDLER(NaClProcessMsg_LaunchLoaderThroughBroker, | |
| 75 OnLaunchLoaderThroughBroker) | |
| 76 IPC_MESSAGE_HANDLER(NaClProcessMsg_LaunchDebugExceptionHandler, | |
| 77 OnLaunchDebugExceptionHandler) | |
| 78 IPC_MESSAGE_HANDLER(NaClProcessMsg_StopBroker, OnStopBroker) | |
| 79 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 80 IPC_END_MESSAGE_MAP() | |
| 81 return handled; | |
| 82 } | |
| 83 | |
| 84 void NaClBrokerListener::OnChannelError() { | |
| 85 // The browser died unexpectedly, quit to avoid a zombie process. | |
| 86 base::MessageLoop::current()->Quit(); | |
| 87 } | |
| 88 | |
| 89 void NaClBrokerListener::OnLaunchLoaderThroughBroker( | |
| 90 const std::string& loader_channel_id) { | |
| 91 base::ProcessHandle loader_process = 0; | |
| 92 base::ProcessHandle loader_handle_in_browser = 0; | |
| 93 | |
| 94 // Create the path to the nacl broker/loader executable - it's the executable | |
| 95 // this code is running in. | |
| 96 base::FilePath exe_path; | |
| 97 PathService::Get(base::FILE_EXE, &exe_path); | |
| 98 if (!exe_path.empty()) { | |
| 99 CommandLine* cmd_line = new CommandLine(exe_path); | |
| 100 nacl::CopyNaClCommandLineArguments(cmd_line); | |
| 101 | |
| 102 cmd_line->AppendSwitchASCII(switches::kProcessType, | |
| 103 switches::kNaClLoaderProcess); | |
| 104 | |
| 105 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, | |
| 106 loader_channel_id); | |
| 107 | |
| 108 loader_process = content::StartSandboxedProcess(this, cmd_line); | |
| 109 if (loader_process) { | |
| 110 DuplicateHandle(::GetCurrentProcess(), loader_process, | |
| 111 browser_handle_, &loader_handle_in_browser, | |
| 112 PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION , FALSE, 0); | |
| 113 base::CloseProcessHandle(loader_process); | |
| 114 } | |
| 115 } | |
| 116 channel_->Send(new NaClProcessMsg_LoaderLaunched(loader_channel_id, | |
| 117 loader_handle_in_browser)); | |
| 118 } | |
| 119 | |
| 120 void NaClBrokerListener::OnLaunchDebugExceptionHandler( | |
| 121 int32 pid, base::ProcessHandle process_handle, | |
| 122 const std::string& startup_info) { | |
| 123 NaClStartDebugExceptionHandlerThread( | |
| 124 process_handle, startup_info, | |
| 125 base::MessageLoopProxy::current(), | |
| 126 base::Bind(SendReply, channel_.get(), pid)); | |
| 127 } | |
| 128 | |
| 129 void NaClBrokerListener::OnStopBroker() { | |
| 130 base::MessageLoop::current()->Quit(); | |
| 131 } | |
| OLD | NEW |