diff options
author | cevans@chromium.org <cevans@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-23 03:49:10 +0000 |
---|---|---|
committer | cevans@chromium.org <cevans@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-23 03:49:10 +0000 |
commit | 313b80bd2c5b7257d8daa2ef4aef0ee5b6e1555c (patch) | |
tree | 47d61470586f795d0f066f3e1d869505bff8de0f /content | |
parent | 02f2de67ceeb9851a87391ef2a00a30661e20bc2 (diff) | |
download | chromium_src-313b80bd2c5b7257d8daa2ef4aef0ee5b6e1555c.zip chromium_src-313b80bd2c5b7257d8daa2ef4aef0ee5b6e1555c.tar.gz chromium_src-313b80bd2c5b7257d8daa2ef4aef0ee5b6e1555c.tar.bz2 |
Enhance --enable-strict-site-isolation to prevent a site-isolated renderer
process from seeing or using cookies for other origins.
Review URL: http://codereview.chromium.org/8496027
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111310 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/child_process_security_policy.cc | 33 | ||||
-rw-r--r-- | content/browser/child_process_security_policy.h | 11 | ||||
-rw-r--r-- | content/browser/renderer_host/render_message_filter.cc | 24 | ||||
-rw-r--r-- | content/browser/renderer_host/resource_dispatcher_host.cc | 11 | ||||
-rw-r--r-- | content/browser/site_instance.cc | 19 | ||||
-rw-r--r-- | content/browser/site_instance.h | 3 | ||||
-rw-r--r-- | content/public/common/content_switches.cc | 8 | ||||
-rw-r--r-- | content/renderer/render_view_impl.cc | 16 |
8 files changed, 115 insertions, 10 deletions
diff --git a/content/browser/child_process_security_policy.cc b/content/browser/child_process_security_policy.cc index c2ea66c..cd61fd4 100644 --- a/content/browser/child_process_security_policy.cc +++ b/content/browser/child_process_security_policy.cc @@ -10,6 +10,7 @@ #include "base/platform_file.h" #include "base/stl_util.h" #include "base/string_util.h" +#include "content/browser/site_instance.h" #include "content/public/common/bindings_policy.h" #include "content/public/common/url_constants.h" #include "googleurl/src/gurl.h" @@ -98,6 +99,17 @@ class ChildProcessSecurityPolicy::SecurityState { return false; } + bool CanUseCookiesForOrigin(const GURL& gurl) { + if (origin_lock_.is_empty()) + return true; + GURL site_gurl = SiteInstance::GetSiteForURL(NULL, gurl); + return origin_lock_ == site_gurl; + } + + void LockToOrigin(const GURL& gurl) { + origin_lock_ = gurl; + } + bool has_web_ui_bindings() const { return enabled_bindings_ & content::BINDINGS_POLICY_WEB_UI; } @@ -124,6 +136,8 @@ class ChildProcessSecurityPolicy::SecurityState { bool can_read_raw_cookies_; + GURL origin_lock_; + DISALLOW_COPY_AND_ASSIGN(SecurityState); }; @@ -449,3 +463,22 @@ bool ChildProcessSecurityPolicy::ChildProcessHasPermissionsForFile( return false; return state->second->HasPermissionsForFile(file, permissions); } + +bool ChildProcessSecurityPolicy::CanUseCookiesForOrigin(int child_id, + const GURL& gurl) { + base::AutoLock lock(lock_); + SecurityStateMap::iterator state = security_state_.find(child_id); + if (state == security_state_.end()) + return false; + return state->second->CanUseCookiesForOrigin(gurl); +} + +void ChildProcessSecurityPolicy::LockToOrigin(int child_id, const GURL& gurl) { + // "gurl" can be currently empty in some cases, such as file://blah. + DCHECK(SiteInstance::GetSiteForURL(NULL, gurl) == gurl); + base::AutoLock lock(lock_); + SecurityStateMap::iterator state = security_state_.find(child_id); + DCHECK(state != security_state_.end()); + state->second->LockToOrigin(gurl); +} + diff --git a/content/browser/child_process_security_policy.h b/content/browser/child_process_security_policy.h index ac01b2e..2d8792e 100644 --- a/content/browser/child_process_security_policy.h +++ b/content/browser/child_process_security_policy.h @@ -141,6 +141,17 @@ class CONTENT_EXPORT ChildProcessSecurityPolicy { // Returns true if the specified child_id has been granted ReadRawCookies. bool CanReadRawCookies(int child_id); + // Returns true if the process is permitted to see and use the cookies for + // the given origin. + // Only might return false if the very experimental + // --enable-strict-site-isolation is used. + bool CanUseCookiesForOrigin(int child_id, const GURL& gurl); + + // Sets the process as only permitted to use and see the cookies for the + // given origin. + // Only used if the very experimental --enable-strict-site-isolation is used. + void LockToOrigin(int child_id, const GURL& gurl); + private: friend class ChildProcessSecurityPolicyInProcessBrowserTest; FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyInProcessBrowserTest, diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index 3c08ac0..672b19f 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -413,6 +413,11 @@ void RenderMessageFilter::OnSetCookie(const IPC::Message& message, const GURL& url, const GURL& first_party_for_cookies, const std::string& cookie) { + ChildProcessSecurityPolicy* policy = + ChildProcessSecurityPolicy::GetInstance(); + if (!policy->CanUseCookiesForOrigin(render_process_id_, url)) + return; + net::CookieOptions options; if (content::GetContentClient()->browser()->AllowSetCookie( url, first_party_for_cookies, cookie, @@ -428,6 +433,13 @@ void RenderMessageFilter::OnSetCookie(const IPC::Message& message, void RenderMessageFilter::OnGetCookies(const GURL& url, const GURL& first_party_for_cookies, IPC::Message* reply_msg) { + ChildProcessSecurityPolicy* policy = + ChildProcessSecurityPolicy::GetInstance(); + if (!policy->CanUseCookiesForOrigin(render_process_id_, url)) { + SendGetCookiesResponse(reply_msg, std::string()); + return; + } + net::URLRequestContext* context = GetRequestContextForURL(url); net::CookieMonster* cookie_monster = context->cookie_store()->GetCookieMonster(); @@ -440,13 +452,16 @@ void RenderMessageFilter::OnGetRawCookies( const GURL& url, const GURL& first_party_for_cookies, IPC::Message* reply_msg) { + ChildProcessSecurityPolicy* policy = + ChildProcessSecurityPolicy::GetInstance(); // Only return raw cookies to trusted renderers or if this request is // not targeted to an an external host like ChromeFrame. // TODO(ananta) We need to support retreiving raw cookies from external // hosts. - if (!ChildProcessSecurityPolicy::GetInstance()->CanReadRawCookies( - render_process_id_)) { + if (!policy->CanReadRawCookies(render_process_id_) || + !policy->CanUseCookiesForOrigin(render_process_id_, url)) { SendGetRawCookiesResponse(reply_msg, net::CookieList()); + return; } // We check policy here to avoid sending back cookies that would not normally @@ -462,6 +477,11 @@ void RenderMessageFilter::OnGetRawCookies( void RenderMessageFilter::OnDeleteCookie(const GURL& url, const std::string& cookie_name) { + ChildProcessSecurityPolicy* policy = + ChildProcessSecurityPolicy::GetInstance(); + if (!policy->CanUseCookiesForOrigin(render_process_id_, url)) + return; + net::URLRequestContext* context = GetRequestContextForURL(url); context->cookie_store()->DeleteCookieAsync(url, cookie_name, base::Closure()); } diff --git a/content/browser/renderer_host/resource_dispatcher_host.cc b/content/browser/renderer_host/resource_dispatcher_host.cc index 46d2cc2..de6f0af 100644 --- a/content/browser/renderer_host/resource_dispatcher_host.cc +++ b/content/browser/renderer_host/resource_dispatcher_host.cc @@ -544,11 +544,18 @@ void ResourceDispatcherHost::BeginRequest( if (sync_result) load_flags |= net::LOAD_IGNORE_LIMITS; + ChildProcessSecurityPolicy* policy = + ChildProcessSecurityPolicy::GetInstance(); + if (!policy->CanUseCookiesForOrigin(child_id, request_data.url)) { + load_flags |= (net::LOAD_DO_NOT_SEND_COOKIES | + net::LOAD_DO_NOT_SEND_AUTH_DATA | + net::LOAD_DO_NOT_SAVE_COOKIES); + } + // Raw headers are sensitive, as they inclide Cookie/Set-Cookie, so only // allow requesting them if requestor has ReadRawCookies permission. if ((load_flags & net::LOAD_REPORT_RAW_HEADERS) - && !ChildProcessSecurityPolicy::GetInstance()-> - CanReadRawCookies(child_id)) { + && !policy->CanReadRawCookies(child_id)) { VLOG(1) << "Denied unathorized request for raw headers"; load_flags &= ~net::LOAD_REPORT_RAW_HEADERS; } diff --git a/content/browser/site_instance.cc b/content/browser/site_instance.cc index 50672ef..b8c55b6 100644 --- a/content/browser/site_instance.cc +++ b/content/browser/site_instance.cc @@ -4,13 +4,16 @@ #include "content/browser/site_instance.h" +#include "base/command_line.h" #include "content/browser/browsing_instance.h" +#include "content/browser/child_process_security_policy.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/webui/web_ui_factory.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/render_process_host_factory.h" +#include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "net/base/registry_controlled_domain.h" @@ -87,6 +90,9 @@ content::RenderProcessHost* SiteInstance::GetProcess() { // Make sure the process starts at the right max_page_id, and ensure that // we send an update to the renderer process. process_->UpdateAndSendMaxPageID(max_page_id_); + + if (has_site_) + LockToOrigin(); } DCHECK(process_); @@ -111,6 +117,9 @@ void SiteInstance::SetSite(const GURL& url) { // the same BrowsingInstance, because all same-site pages within a // BrowsingInstance can script each other. browsing_instance_->RegisterSiteInstance(this); + + if (process_) + LockToOrigin(); } bool SiteInstance::HasRelatedSiteInstance(const GURL& url) { @@ -230,3 +239,13 @@ void SiteInstance::Observe(int type, if (rph == process_) process_ = NULL; } + +void SiteInstance::LockToOrigin() { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kEnableStrictSiteIsolation)) { + ChildProcessSecurityPolicy* policy = + ChildProcessSecurityPolicy::GetInstance(); + policy->LockToOrigin(process_->GetID(), site_); + } +} + diff --git a/content/browser/site_instance.h b/content/browser/site_instance.h index 057ed59..9feccfc 100644 --- a/content/browser/site_instance.h +++ b/content/browser/site_instance.h @@ -172,6 +172,9 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance>, const content::NotificationSource& source, const content::NotificationDetails& details) OVERRIDE; + // Used to restrict a process' origin access rights. + void LockToOrigin(); + // The next available SiteInstance ID. static int32 next_site_instance_id_; diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 01154ac..08e6e50 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc @@ -245,7 +245,13 @@ const char kEnableSeccompSandbox[] = "enable-seccomp-sandbox"; // Enables StatsTable, logging statistics to a global named shared memory table. const char kEnableStatsTable[] = "enable-stats-table"; -// Experimentally ensure each renderer process has pages from only one site. +// Experimentally ensures that each renderer process: +// 1) Only handles rendering for a single page. +// (Note that a page can reference content from multiple origins due to images, +// iframes, etc). +// 2) Only has authority to see or use cookies for the page's top-level origin. +// (So if a.com iframe's b.com, the b.com network request will be sent without +// cookies). // This is expected to break compatibility with many pages for now. const char kEnableStrictSiteIsolation[] = "enable-strict-site-isolation"; diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 502bb67..53d0e97 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -1990,11 +1990,17 @@ WebNavigationPolicy RenderViewImpl::decidePolicyForNavigation( // boundaries. This is currently expected to break some script calls and // navigations, such as form submissions. const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - if (!frame->parent() && (is_content_initiated || is_redirect) && - command_line.HasSwitch(switches::kEnableStrictSiteIsolation)) { - GURL referrer(request.httpHeaderField(WebString::fromUTF8("Referer"))); - OpenURL(frame, url, referrer, default_policy); - return WebKit::WebNavigationPolicyIgnore; + if (command_line.HasSwitch(switches::kEnableStrictSiteIsolation) && + !frame->parent() && (is_content_initiated || is_redirect)) { + WebString origin_str = frame->document().securityOrigin().toString(); + GURL frame_url(origin_str.utf8().data()); + // TODO(cevans): revisit whether this origin check is still necessary once + // crbug.com/101395 is fixed. + if (frame_url.GetOrigin() != url.GetOrigin()) { + GURL referrer(request.httpHeaderField(WebString::fromUTF8("Referer"))); + OpenURL(frame, url, referrer, default_policy); + return WebKit::WebNavigationPolicyIgnore; + } } // If the browser is interested, then give it a chance to look at top level |