Chromium Code Reviews| 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/browser/nacl_host_message_filter.h" | 5 #include "components/nacl/browser/nacl_host_message_filter.h" |
| 6 | 6 |
| 7 #include "base/sys_info.h" | 7 #include "base/sys_info.h" |
| 8 #include "components/nacl/browser/nacl_browser.h" | 8 #include "components/nacl/browser/nacl_browser.h" |
| 9 #include "components/nacl/browser/nacl_file_host.h" | 9 #include "components/nacl/browser/nacl_file_host.h" |
| 10 #include "components/nacl/browser/nacl_process_host.h" | 10 #include "components/nacl/browser/nacl_process_host.h" |
| 11 #include "components/nacl/browser/pnacl_host.h" | 11 #include "components/nacl/browser/pnacl_host.h" |
| 12 #include "components/nacl/common/nacl_host_messages.h" | 12 #include "components/nacl/common/nacl_host_messages.h" |
| 13 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
| 14 #include "content/public/browser/plugin_service.h" | 14 #include "content/public/browser/plugin_service.h" |
| 15 #include "content/public/browser/render_process_host.h" | 15 #include "content/public/browser/render_process_host.h" |
| 16 #include "content/public/browser/web_contents.h" | 16 #include "content/public/browser/web_contents.h" |
| 17 #include "ipc/ipc_platform_file.h" | 17 #include "ipc/ipc_platform_file.h" |
| 18 #include "native_client/src/public/nacl_file_info.h" | 18 #include "native_client/src/public/nacl_file_info.h" |
| 19 #include "net/url_request/url_request_context.h" | 19 #include "net/url_request/url_request_context.h" |
| 20 #include "net/url_request/url_request_context_getter.h" | 20 #include "net/url_request/url_request_context_getter.h" |
| 21 #include "ppapi/shared_impl/ppapi_permissions.h" | 21 #include "ppapi/shared_impl/ppapi_permissions.h" |
| 22 #include "url/gurl.h" | 22 #include "url/gurl.h" |
| 23 | 23 |
| 24 namespace nacl { | 24 namespace nacl { |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 // The maximum number of resource file handles NaClProcessMsg_Start message | |
| 29 // can have. | |
| 30 // TODO(yusukes): Increase the number. | |
| 31 const size_t kMaxPreOpenResourceFiles = 2; | |
| 32 | |
| 28 ppapi::PpapiPermissions GetNaClPermissions( | 33 ppapi::PpapiPermissions GetNaClPermissions( |
| 29 uint32 permission_bits, | 34 uint32 permission_bits, |
| 30 content::BrowserContext* browser_context, | 35 content::BrowserContext* browser_context, |
| 31 const GURL& document_url) { | 36 const GURL& document_url) { |
| 32 // Only allow NaCl plugins to request certain permissions. We don't want | 37 // Only allow NaCl plugins to request certain permissions. We don't want |
| 33 // a compromised renderer to be able to start a nacl plugin with e.g. Flash | 38 // a compromised renderer to be able to start a nacl plugin with e.g. Flash |
| 34 // permissions which may expand the surface area of the sandbox. | 39 // permissions which may expand the surface area of the sandbox. |
| 35 uint32 masked_bits = permission_bits & ppapi::PERMISSION_DEV; | 40 uint32 masked_bits = permission_bits & ppapi::PERMISSION_DEV; |
| 36 if (content::PluginService::GetInstance()->PpapiDevChannelSupported( | 41 if (content::PluginService::GetInstance()->PpapiDevChannelSupported( |
| 37 browser_context, document_url)) | 42 browser_context, document_url)) |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 111 return handled; | 116 return handled; |
| 112 } | 117 } |
| 113 | 118 |
| 114 net::HostResolver* NaClHostMessageFilter::GetHostResolver() { | 119 net::HostResolver* NaClHostMessageFilter::GetHostResolver() { |
| 115 return request_context_->GetURLRequestContext()->host_resolver(); | 120 return request_context_->GetURLRequestContext()->host_resolver(); |
| 116 } | 121 } |
| 117 | 122 |
| 118 void NaClHostMessageFilter::OnLaunchNaCl( | 123 void NaClHostMessageFilter::OnLaunchNaCl( |
| 119 const nacl::NaClLaunchParams& launch_params, | 124 const nacl::NaClLaunchParams& launch_params, |
| 120 IPC::Message* reply_msg) { | 125 IPC::Message* reply_msg) { |
| 126 const std::vector<nacl::NaClResourceFileInfo> empty; | |
| 121 // If we're running llc or ld for the PNaCl translator, we don't need to look | 127 // If we're running llc or ld for the PNaCl translator, we don't need to look |
| 122 // up permissions, and we don't have the right browser state to look up some | 128 // up permissions, and we don't have the right browser state to look up some |
| 123 // of the whitelisting parameters anyway. | 129 // of the whitelisting parameters anyway. |
| 124 if (launch_params.process_type == kPNaClTranslatorProcessType) { | 130 if (launch_params.process_type == kPNaClTranslatorProcessType) { |
| 125 uint32 perms = launch_params.permission_bits & ppapi::PERMISSION_DEV; | 131 uint32 perms = launch_params.permission_bits & ppapi::PERMISSION_DEV; |
| 126 LaunchNaClContinuation( | 132 LaunchNaClContinuation( |
| 127 launch_params, | 133 launch_params, |
| 128 reply_msg, | 134 reply_msg, |
| 135 empty, | |
| 129 ppapi::PpapiPermissions(perms)); | 136 ppapi::PpapiPermissions(perms)); |
| 130 return; | 137 return; |
| 131 } | 138 } |
| 132 content::BrowserThread::PostTaskAndReplyWithResult( | 139 content::BrowserThread::PostTaskAndReplyWithResult( |
| 133 content::BrowserThread::UI, | 140 content::BrowserThread::UI, |
| 134 FROM_HERE, | 141 FROM_HERE, |
| 135 base::Bind(&GetPpapiPermissions, | 142 base::Bind(&GetPpapiPermissions, |
| 136 launch_params.permission_bits, | 143 launch_params.permission_bits, |
| 137 render_process_id_, | 144 render_process_id_, |
| 138 launch_params.render_view_id), | 145 launch_params.render_view_id), |
| 139 base::Bind(&NaClHostMessageFilter::LaunchNaClContinuation, | 146 base::Bind(&NaClHostMessageFilter::LaunchNaClContinuation, |
| 140 this, | 147 this, |
| 141 launch_params, | 148 launch_params, |
| 142 reply_msg)); | 149 reply_msg, |
| 150 empty)); | |
| 151 } | |
| 152 | |
| 153 void NaClHostMessageFilter::BatchOpenResourceFiles( | |
| 154 const nacl::NaClLaunchParams& launch_params, | |
| 155 IPC::Message* reply_msg, | |
| 156 ppapi::PpapiPermissions permissions) { | |
| 157 content::RenderViewHost* rvh = content::RenderViewHost::FromID( | |
|
Mark Seaborn
2015/02/25 20:01:23
You're doing things in this PostBlockingPoolTask()
Yusuke Sato
2015/03/01 06:59:37
No, it's not valid. RVH::FromID has to be called i
| |
| 158 render_process_id(), launch_params.render_view_id); | |
| 159 if (!rvh) { | |
| 160 BadMessageReceived(); // Kill the renderer. | |
| 161 return; | |
| 162 } | |
| 163 | |
| 164 std::vector<nacl::NaClResourceFileInfo> prefetched_resource_files_info; | |
| 165 // TODO(yusukes): Support SFI mode. | |
| 166 if (launch_params.uses_nonsfi_mode) { | |
|
Yusuke Sato
2015/03/01 06:59:37
removed the IF
| |
| 167 content::SiteInstance* site_instance = rvh->GetSiteInstance(); | |
| 168 for (size_t i = 0; | |
| 169 i < launch_params.prefetched_resource_files.size(); ++i) { | |
| 170 nacl::NaClResourceFileInfo prefetched_resource_file; | |
| 171 GURL gurl(launch_params.prefetched_resource_files[i].first); | |
| 172 // IMPORTANT SECURITY CHECK: Do the same check as OpenNaClExecutable() | |
| 173 // in nacl_file_host.cc. | |
| 174 if (!content::SiteInstance::IsSameWebSite( | |
| 175 site_instance->GetBrowserContext(), | |
| 176 site_instance->GetSiteURL(), | |
| 177 gurl)) { | |
| 178 continue; | |
| 179 } | |
| 180 if (!nacl::NaClBrowser::GetDelegate()->MapUrlToLocalFilePath( | |
| 181 gurl, | |
| 182 true, // blocking | |
|
Mark Seaborn
2015/02/25 20:01:23
Nit: "use_blocking_api" (for consistency)
Yusuke Sato
2015/03/01 06:59:37
Done.
| |
| 183 profile_directory_, | |
| 184 &prefetched_resource_file.file_path)) { | |
| 185 continue; | |
| 186 } | |
| 187 base::File file = nacl::OpenNaClReadExecImpl( | |
| 188 prefetched_resource_file.file_path, true /* is_executable */); | |
| 189 if (!file.IsValid()) | |
| 190 continue; | |
| 191 | |
| 192 prefetched_resource_file.file = | |
| 193 IPC::TakeFileHandleForProcess(file.Pass(), PeerHandle()); | |
| 194 prefetched_resource_file.file_key = | |
| 195 launch_params.prefetched_resource_files[i].second; | |
| 196 | |
| 197 prefetched_resource_files_info.push_back(prefetched_resource_file); | |
| 198 if (prefetched_resource_files_info.size() > kMaxPreOpenResourceFiles) | |
| 199 break; | |
| 200 } | |
| 201 } | |
| 202 | |
| 203 nacl::NaClLaunchParams new_launch_params(launch_params); | |
| 204 new_launch_params.prefetched_resource_files.clear(); | |
| 205 | |
| 206 if (!content::BrowserThread::PostTask( | |
| 207 content::BrowserThread::IO, | |
| 208 FROM_HERE, | |
| 209 base::Bind(&NaClHostMessageFilter::LaunchNaClContinuation, | |
| 210 this, | |
| 211 new_launch_params, | |
| 212 reply_msg, | |
| 213 prefetched_resource_files_info, | |
| 214 permissions))) { | |
| 215 for (size_t i = 0; i < prefetched_resource_files_info.size(); ++i) { | |
|
Mark Seaborn
2015/02/25 20:01:23
This error handling seems unnecessary. When would
Yusuke Sato
2015/03/01 06:59:37
Removed. Looks like PostTask always returns true a
| |
| 216 // The base::File destructor will close the file. | |
| 217 base::File file(IPC::PlatformFileForTransitToFile( | |
| 218 prefetched_resource_files_info[i].file)); | |
| 219 } | |
| 220 NaClHostMsg_LaunchNaCl::WriteReplyParams( | |
| 221 reply_msg, | |
| 222 NaClLaunchResult(), | |
| 223 std::string("Failed to open resource files")); | |
| 224 Send(reply_msg); | |
| 225 } | |
| 143 } | 226 } |
| 144 | 227 |
| 145 void NaClHostMessageFilter::LaunchNaClContinuation( | 228 void NaClHostMessageFilter::LaunchNaClContinuation( |
| 146 const nacl::NaClLaunchParams& launch_params, | 229 const nacl::NaClLaunchParams& launch_params, |
| 147 IPC::Message* reply_msg, | 230 IPC::Message* reply_msg, |
| 231 const std::vector< | |
| 232 nacl::NaClResourceFileInfo>& prefetched_resource_files_info, | |
| 148 ppapi::PpapiPermissions permissions) { | 233 ppapi::PpapiPermissions permissions) { |
| 234 if (!launch_params.prefetched_resource_files.empty()) { | |
| 235 // Process a list of resource file URLs in | |
| 236 // |launch_params.prefetched_resource_files|. | |
| 237 // BatchOpenResourceFiles calls this function again with an empty | |
|
Mark Seaborn
2015/02/25 20:01:23
It seems kind of hacky for a function to call itse
Yusuke Sato
2015/03/01 06:59:37
Done.
| |
| 238 // |launch_params.prefetched_resource_files|. | |
| 239 DCHECK(prefetched_resource_files_info.empty()); | |
| 240 if (!content::BrowserThread::PostBlockingPoolTask( | |
| 241 FROM_HERE, | |
| 242 base::Bind(&NaClHostMessageFilter::BatchOpenResourceFiles, | |
| 243 this, | |
| 244 launch_params, | |
| 245 reply_msg, | |
| 246 permissions))) { | |
| 247 NaClHostMsg_LaunchNaCl::WriteReplyParams( | |
| 248 reply_msg, | |
| 249 NaClLaunchResult(), | |
| 250 std::string("Failed to open resource files")); | |
| 251 Send(reply_msg); | |
| 252 } | |
| 253 return; | |
| 254 } | |
| 255 | |
| 149 NaClFileToken nexe_token = { | 256 NaClFileToken nexe_token = { |
| 150 launch_params.nexe_token_lo, // lo | 257 launch_params.nexe_token_lo, // lo |
| 151 launch_params.nexe_token_hi // hi | 258 launch_params.nexe_token_hi // hi |
| 152 }; | 259 }; |
| 153 | 260 |
| 154 base::PlatformFile nexe_file; | 261 base::PlatformFile nexe_file; |
| 155 #if defined(OS_WIN) | 262 #if defined(OS_WIN) |
| 156 // Duplicate the nexe file handle from the renderer process into the browser | 263 // Duplicate the nexe file handle from the renderer process into the browser |
| 157 // process. | 264 // process. |
| 158 if (!::DuplicateHandle(PeerHandle(), | 265 if (!::DuplicateHandle(PeerHandle(), |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 173 nexe_file = | 280 nexe_file = |
| 174 IPC::PlatformFileForTransitToPlatformFile(launch_params.nexe_file); | 281 IPC::PlatformFileForTransitToPlatformFile(launch_params.nexe_file); |
| 175 #else | 282 #else |
| 176 #error Unsupported platform. | 283 #error Unsupported platform. |
| 177 #endif | 284 #endif |
| 178 | 285 |
| 179 NaClProcessHost* host = new NaClProcessHost( | 286 NaClProcessHost* host = new NaClProcessHost( |
| 180 GURL(launch_params.manifest_url), | 287 GURL(launch_params.manifest_url), |
| 181 base::File(nexe_file), | 288 base::File(nexe_file), |
| 182 nexe_token, | 289 nexe_token, |
| 290 prefetched_resource_files_info, | |
| 183 permissions, | 291 permissions, |
| 184 launch_params.render_view_id, | 292 launch_params.render_view_id, |
| 185 launch_params.permission_bits, | 293 launch_params.permission_bits, |
| 186 launch_params.uses_nonsfi_mode, | 294 launch_params.uses_nonsfi_mode, |
| 187 off_the_record_, | 295 off_the_record_, |
| 188 launch_params.process_type, | 296 launch_params.process_type, |
| 189 profile_directory_); | 297 profile_directory_); |
| 190 GURL manifest_url(launch_params.manifest_url); | 298 GURL manifest_url(launch_params.manifest_url); |
| 191 base::FilePath manifest_path; | 299 base::FilePath manifest_path; |
| 192 // We're calling MapUrlToLocalFilePath with the non-blocking API | 300 // We're calling MapUrlToLocalFilePath with the non-blocking API |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 reply_msg); | 404 reply_msg); |
| 297 } | 405 } |
| 298 | 406 |
| 299 void NaClHostMessageFilter::OnNaClDebugEnabledForURL(const GURL& nmf_url, | 407 void NaClHostMessageFilter::OnNaClDebugEnabledForURL(const GURL& nmf_url, |
| 300 bool* should_debug) { | 408 bool* should_debug) { |
| 301 *should_debug = | 409 *should_debug = |
| 302 nacl::NaClBrowser::GetDelegate()->URLMatchesDebugPatterns(nmf_url); | 410 nacl::NaClBrowser::GetDelegate()->URLMatchesDebugPatterns(nmf_url); |
| 303 } | 411 } |
| 304 | 412 |
| 305 } // namespace nacl | 413 } // namespace nacl |
| OLD | NEW |