summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorcevans@chromium.org <cevans@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-23 03:49:10 +0000
committercevans@chromium.org <cevans@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-23 03:49:10 +0000
commit313b80bd2c5b7257d8daa2ef4aef0ee5b6e1555c (patch)
tree47d61470586f795d0f066f3e1d869505bff8de0f /content
parent02f2de67ceeb9851a87391ef2a00a30661e20bc2 (diff)
downloadchromium_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.cc33
-rw-r--r--content/browser/child_process_security_policy.h11
-rw-r--r--content/browser/renderer_host/render_message_filter.cc24
-rw-r--r--content/browser/renderer_host/resource_dispatcher_host.cc11
-rw-r--r--content/browser/site_instance.cc19
-rw-r--r--content/browser/site_instance.h3
-rw-r--r--content/public/common/content_switches.cc8
-rw-r--r--content/renderer/render_view_impl.cc16
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