Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(492)

Side by Side Diff: content/browser/child_process_security_policy_impl.cc

Issue 2364633004: Lock down the registration of blob:chrome-extension:// URLs (Closed)
Patch Set: Pare down CL Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "content/browser/child_process_security_policy_impl.h" 5 #include "content/browser/child_process_security_policy_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 void RevokeReadRawCookies() { 195 void RevokeReadRawCookies() {
196 can_read_raw_cookies_ = false; 196 can_read_raw_cookies_ = false;
197 } 197 }
198 198
199 void GrantPermissionForMidiSysEx() { 199 void GrantPermissionForMidiSysEx() {
200 can_send_midi_sysex_ = true; 200 can_send_midi_sysex_ = true;
201 } 201 }
202 202
203 // Determine whether permission has been granted to commit |url|. 203 // Determine whether permission has been granted to commit |url|.
204 bool CanCommitURL(const GURL& url) { 204 bool CanCommitURL(const GURL& url) {
205 DCHECK(!url.SchemeIsBlob() && !url.SchemeIsFileSystem())
206 << "inner_url extraction should be done already.";
205 // Having permission to a scheme implies permission to all of its URLs. 207 // Having permission to a scheme implies permission to all of its URLs.
206 SchemeMap::const_iterator scheme_judgment( 208 SchemeMap::const_iterator scheme_judgment(
207 scheme_policy_.find(url.scheme())); 209 scheme_policy_.find(url.scheme()));
208 if (scheme_judgment != scheme_policy_.end()) 210 if (scheme_judgment != scheme_policy_.end())
209 return scheme_judgment->second; 211 return scheme_judgment->second;
210 212
211 // Otherwise, check for permission for specific origin. 213 // Otherwise, check for permission for specific origin.
212 if (base::ContainsKey(origin_set_, url::Origin(url))) 214 if (base::ContainsKey(origin_set_, url::Origin(url)))
213 return true; 215 return true;
214 216
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 DISALLOW_COPY_AND_ASSIGN(SecurityState); 321 DISALLOW_COPY_AND_ASSIGN(SecurityState);
320 }; 322 };
321 323
322 ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() { 324 ChildProcessSecurityPolicyImpl::ChildProcessSecurityPolicyImpl() {
323 // We know about these schemes and believe them to be safe. 325 // We know about these schemes and believe them to be safe.
324 RegisterWebSafeScheme(url::kHttpScheme); 326 RegisterWebSafeScheme(url::kHttpScheme);
325 RegisterWebSafeScheme(url::kHttpsScheme); 327 RegisterWebSafeScheme(url::kHttpsScheme);
326 RegisterWebSafeScheme(url::kFtpScheme); 328 RegisterWebSafeScheme(url::kFtpScheme);
327 RegisterWebSafeScheme(url::kDataScheme); 329 RegisterWebSafeScheme(url::kDataScheme);
328 RegisterWebSafeScheme("feed"); 330 RegisterWebSafeScheme("feed");
331
332 // TODO(nick): blob: and filesystem: schemes embed other origins,
333 // so we should not treat them as web safe. Remove callers of
334 // IsWebSafeScheme(), and then eliminate the next two lines.
329 RegisterWebSafeScheme(url::kBlobScheme); 335 RegisterWebSafeScheme(url::kBlobScheme);
330 RegisterWebSafeScheme(url::kFileSystemScheme); 336 RegisterWebSafeScheme(url::kFileSystemScheme);
331 337
332 // We know about the following pseudo schemes and treat them specially. 338 // We know about the following pseudo schemes and treat them specially.
333 RegisterPseudoScheme(url::kAboutScheme); 339 RegisterPseudoScheme(url::kAboutScheme);
334 RegisterPseudoScheme(url::kJavaScriptScheme); 340 RegisterPseudoScheme(url::kJavaScriptScheme);
335 RegisterPseudoScheme(kViewSourceScheme); 341 RegisterPseudoScheme(kViewSourceScheme);
336 RegisterPseudoScheme(kHttpSuboriginScheme); 342 RegisterPseudoScheme(kHttpSuboriginScheme);
337 RegisterPseudoScheme(kHttpsSuboriginScheme); 343 RegisterPseudoScheme(kHttpsSuboriginScheme);
338 } 344 }
339 345
340 ChildProcessSecurityPolicyImpl::~ChildProcessSecurityPolicyImpl() { 346 ChildProcessSecurityPolicyImpl::~ChildProcessSecurityPolicyImpl() {
341 web_safe_schemes_.clear(); 347 schemes_okay_to_request_in_any_process_.clear();
348 schemes_okay_to_commit_in_any_process_.clear();
342 pseudo_schemes_.clear(); 349 pseudo_schemes_.clear();
343 security_state_.clear(); 350 security_state_.clear();
344 } 351 }
345 352
346 // static 353 // static
347 ChildProcessSecurityPolicy* ChildProcessSecurityPolicy::GetInstance() { 354 ChildProcessSecurityPolicy* ChildProcessSecurityPolicy::GetInstance() {
348 return ChildProcessSecurityPolicyImpl::GetInstance(); 355 return ChildProcessSecurityPolicyImpl::GetInstance();
349 } 356 }
350 357
351 ChildProcessSecurityPolicyImpl* ChildProcessSecurityPolicyImpl::GetInstance() { 358 ChildProcessSecurityPolicyImpl* ChildProcessSecurityPolicyImpl::GetInstance() {
(...skipping 14 matching lines...) Expand all
366 373
367 void ChildProcessSecurityPolicyImpl::Remove(int child_id) { 374 void ChildProcessSecurityPolicyImpl::Remove(int child_id) {
368 base::AutoLock lock(lock_); 375 base::AutoLock lock(lock_);
369 security_state_.erase(child_id); 376 security_state_.erase(child_id);
370 worker_map_.erase(child_id); 377 worker_map_.erase(child_id);
371 } 378 }
372 379
373 void ChildProcessSecurityPolicyImpl::RegisterWebSafeScheme( 380 void ChildProcessSecurityPolicyImpl::RegisterWebSafeScheme(
374 const std::string& scheme) { 381 const std::string& scheme) {
375 base::AutoLock lock(lock_); 382 base::AutoLock lock(lock_);
376 DCHECK_EQ(0U, web_safe_schemes_.count(scheme)) << "Add schemes at most once."; 383 DCHECK_EQ(0U, schemes_okay_to_request_in_any_process_.count(scheme))
384 << "Add schemes at most once.";
377 DCHECK_EQ(0U, pseudo_schemes_.count(scheme)) 385 DCHECK_EQ(0U, pseudo_schemes_.count(scheme))
378 << "Web-safe implies not pseudo."; 386 << "Web-safe implies not pseudo.";
379 387
380 web_safe_schemes_.insert(scheme); 388 schemes_okay_to_request_in_any_process_.insert(scheme);
389 schemes_okay_to_commit_in_any_process_.insert(scheme);
390 }
391
392 void ChildProcessSecurityPolicyImpl::RegisterWebSafeIsolatedScheme(
393 const std::string& scheme) {
394 base::AutoLock lock(lock_);
395 DCHECK_EQ(0U, schemes_okay_to_request_in_any_process_.count(scheme))
396 << "Add schemes at most once.";
397 DCHECK_EQ(0U, pseudo_schemes_.count(scheme))
398 << "Web-safe implies not pseudo.";
399
400 schemes_okay_to_request_in_any_process_.insert(scheme);
381 } 401 }
382 402
383 bool ChildProcessSecurityPolicyImpl::IsWebSafeScheme( 403 bool ChildProcessSecurityPolicyImpl::IsWebSafeScheme(
384 const std::string& scheme) { 404 const std::string& scheme) {
385 base::AutoLock lock(lock_); 405 base::AutoLock lock(lock_);
386 406
387 return base::ContainsKey(web_safe_schemes_, scheme); 407 return base::ContainsKey(schemes_okay_to_request_in_any_process_, scheme);
388 } 408 }
389 409
390 void ChildProcessSecurityPolicyImpl::RegisterPseudoScheme( 410 void ChildProcessSecurityPolicyImpl::RegisterPseudoScheme(
391 const std::string& scheme) { 411 const std::string& scheme) {
392 base::AutoLock lock(lock_); 412 base::AutoLock lock(lock_);
393 DCHECK_EQ(0U, pseudo_schemes_.count(scheme)) << "Add schemes at most once."; 413 DCHECK_EQ(0U, pseudo_schemes_.count(scheme)) << "Add schemes at most once.";
394 DCHECK_EQ(0U, web_safe_schemes_.count(scheme)) 414 DCHECK_EQ(0U, schemes_okay_to_request_in_any_process_.count(scheme))
415 << "Pseudo implies not web-safe.";
416 DCHECK_EQ(0U, schemes_okay_to_commit_in_any_process_.count(scheme))
395 << "Pseudo implies not web-safe."; 417 << "Pseudo implies not web-safe.";
396 418
397 pseudo_schemes_.insert(scheme); 419 pseudo_schemes_.insert(scheme);
398 } 420 }
399 421
400 bool ChildProcessSecurityPolicyImpl::IsPseudoScheme( 422 bool ChildProcessSecurityPolicyImpl::IsPseudoScheme(
401 const std::string& scheme) { 423 const std::string& scheme) {
402 base::AutoLock lock(lock_); 424 base::AutoLock lock(lock_);
403 425
404 return base::ContainsKey(pseudo_schemes_, scheme); 426 return base::ContainsKey(pseudo_schemes_, scheme);
405 } 427 }
406 428
407 void ChildProcessSecurityPolicyImpl::GrantRequestURL( 429 void ChildProcessSecurityPolicyImpl::GrantRequestURL(
408 int child_id, const GURL& url) { 430 int child_id, const GURL& url) {
409 431
410 if (!url.is_valid()) 432 if (!url.is_valid())
411 return; // Can't grant the capability to request invalid URLs. 433 return; // Can't grant the capability to request invalid URLs.
412 434
413 if (IsWebSafeScheme(url.scheme())) 435 if (IsWebSafeScheme(url.scheme()))
414 return; // The scheme has already been whitelisted for every child process. 436 return; // The scheme has already been whitelisted for every child process.
415 437
416 if (IsPseudoScheme(url.scheme())) { 438 if (IsPseudoScheme(url.scheme())) {
417 return; // Can't grant the capability to request pseudo schemes. 439 return; // Can't grant the capability to request pseudo schemes.
418 } 440 }
419 441
442 if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) {
443 return; // Don't grant blanket access to blob: or filesystem: schemes.
444 }
445
420 { 446 {
421 base::AutoLock lock(lock_); 447 base::AutoLock lock(lock_);
422 SecurityStateMap::iterator state = security_state_.find(child_id); 448 SecurityStateMap::iterator state = security_state_.find(child_id);
423 if (state == security_state_.end()) 449 if (state == security_state_.end())
424 return; 450 return;
425 451
426 // When the child process has been commanded to request this scheme, 452 // When the child process has been commanded to request this scheme,
427 // we grant it the capability to request all URLs of that scheme. 453 // we grant it the capability to request all URLs of that scheme.
428 state->second->GrantScheme(url.scheme()); 454 state->second->GrantScheme(url.scheme());
429 } 455 }
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 // Every child process can request <about:blank>. 625 // Every child process can request <about:blank>.
600 if (base::LowerCaseEqualsASCII(url.spec(), url::kAboutBlankURL)) 626 if (base::LowerCaseEqualsASCII(url.spec(), url::kAboutBlankURL))
601 return true; 627 return true;
602 // URLs like <about:version>, <about:crash>, <view-source:...> shouldn't be 628 // URLs like <about:version>, <about:crash>, <view-source:...> shouldn't be
603 // requestable by any child process. Also, this case covers 629 // requestable by any child process. Also, this case covers
604 // <javascript:...>, which should be handled internally by the process and 630 // <javascript:...>, which should be handled internally by the process and
605 // not kicked up to the browser. 631 // not kicked up to the browser.
606 return false; 632 return false;
607 } 633 }
608 634
609 if (IsMalformedBlobUrl(url)) 635 // Blob and filesystem URLs require special treatment, since they embed an
610 return false; 636 // inner origin.
637 if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) {
638 if (IsMalformedBlobUrl(url))
639 return false;
640
641 url::Origin origin(url);
642 return origin.unique() || IsWebSafeScheme(origin.scheme()) ||
643 CanCommitURL(child_id, GURL(origin.Serialize()));
644 }
645
646 if (IsWebSafeScheme(url.scheme()))
647 return true;
611 648
612 // If the process can commit the URL, it can request it. 649 // If the process can commit the URL, it can request it.
613 if (CanCommitURL(child_id, url)) 650 if (CanCommitURL(child_id, url))
614 return true; 651 return true;
615 652
616 // Also allow URLs destined for ShellExecute and not the browser itself. 653 // Also allow URLs destined for ShellExecute and not the browser itself.
617 return !GetContentClient()->browser()->IsHandledURL(url) && 654 return !GetContentClient()->browser()->IsHandledURL(url) &&
618 !net::URLRequest::IsHandledURL(url); 655 !net::URLRequest::IsHandledURL(url);
619 } 656 }
620 657
621 bool ChildProcessSecurityPolicyImpl::CanCommitURL(int child_id, 658 bool ChildProcessSecurityPolicyImpl::CanCommitURL(int child_id,
622 const GURL& url) { 659 const GURL& url) {
623 if (!url.is_valid()) 660 if (!url.is_valid())
624 return false; // Can't commit invalid URLs. 661 return false; // Can't commit invalid URLs.
625 662
626 // Of all the pseudo schemes, only about:blank is allowed to commit. 663 // Of all the pseudo schemes, only about:blank is allowed to commit.
627 if (IsPseudoScheme(url.scheme())) 664 if (IsPseudoScheme(url.scheme()))
628 return base::LowerCaseEqualsASCII(url.spec(), url::kAboutBlankURL); 665 return base::LowerCaseEqualsASCII(url.spec(), url::kAboutBlankURL);
629 666
630 if (IsMalformedBlobUrl(url)) 667 // Blob and filesystem URLs require special treatment; validate the inner
631 return false; 668 // origin they embed.
669 if (url.SchemeIsBlob() || url.SchemeIsFileSystem()) {
670 if (IsMalformedBlobUrl(url))
671 return false;
632 672
633 // TODO(creis): Tighten this for Site Isolation, so that a URL from a site 673 url::Origin origin(url);
634 // that is isolated can only be committed in a process dedicated to that site. 674 return origin.unique() || CanCommitURL(child_id, GURL(origin.Serialize()));
635 // CanRequestURL should still allow all web-safe schemes. See 675 }
636 // https://crbug.com/515309.
Charlie Reis 2016/09/28 22:07:16 Can we keep this TODO, or is there a reason that i
ncarter (slow) 2016/09/29 21:01:45 I updated the TODO.
637 if (IsWebSafeScheme(url.scheme()))
638 return true; // The scheme has been white-listed for every child process.
639 676
640 { 677 {
641 base::AutoLock lock(lock_); 678 base::AutoLock lock(lock_);
642 679
680 // Most schemes can commit in any process. Note that we check
681 // schemes_okay_to_commit_in_any_process_ here, which is stricter than
682 // IsWebSafeScheme().
683 if (base::ContainsKey(schemes_okay_to_commit_in_any_process_, url.scheme()))
684 return true;
685
643 SecurityStateMap::iterator state = security_state_.find(child_id); 686 SecurityStateMap::iterator state = security_state_.find(child_id);
644 if (state == security_state_.end()) 687 if (state == security_state_.end())
645 return false; 688 return false;
646 689
647 // Otherwise, we consult the child process's security state to see if it is 690 // Otherwise, we consult the child process's security state to see if it is
648 // allowed to commit the URL. 691 // allowed to commit the URL.
649 return state->second->CanCommitURL(url); 692 return state->second->CanCommitURL(url);
650 } 693 }
651 } 694 }
652 695
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
899 base::AutoLock lock(lock_); 942 base::AutoLock lock(lock_);
900 943
901 SecurityStateMap::iterator state = security_state_.find(child_id); 944 SecurityStateMap::iterator state = security_state_.find(child_id);
902 if (state == security_state_.end()) 945 if (state == security_state_.end())
903 return false; 946 return false;
904 947
905 return state->second->can_send_midi_sysex(); 948 return state->second->can_send_midi_sysex();
906 } 949 }
907 950
908 } // namespace content 951 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698