Commit fc457ca8 authored by Dave Tapuska's avatar Dave Tapuska Committed by Commit Bot

Add boolean indicating whether cross browsing instance frame lookup is allowed.

WebView and extensions allow frame lookup across browsing instances. We wish
to enforce Same Agent restrictions in bindings but for these cases we
cannot. This change adds the ability to mark frames as having
CrossBrowsingInstanceFrameLookup. A folloup change will add a SECURITY_CHECK
to the bindings interface for this.

BUG=970360

Change-Id: I76334a82644161f7b44b07a32847514bf20acecf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1708752Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarAlex Moshchuk <alexmos@chromium.org>
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
Cr-Commit-Position: refs/heads/master@{#684460}
parent baaab7ff
......@@ -319,6 +319,9 @@ class CONTENT_EXPORT RenderFrame : public IPC::Listener,
// a local root.
virtual void UpdateAllLifecyclePhasesAndCompositeForTesting() = 0;
// Sets that cross browsing instance frame lookup is allowed.
virtual void SetAllowsCrossBrowsingInstanceFrameLookup() = 0;
protected:
~RenderFrame() override {}
......
......@@ -6218,6 +6218,9 @@ void RenderFrameImpl::DidCommitNavigationInternal(
DCHECK(!(was_within_same_document && interface_params));
UpdateStateForCommit(item, commit_type, transition);
if (render_view_->renderer_wide_named_frame_lookup())
GetWebFrame()->SetAllowsCrossBrowsingInstanceFrameLookup();
// This invocation must precede any calls to allowScripts(), allowImages(), or
// allowPlugins() for the new page. This ensures that when these functions
// send ViewHostMsg_ContentBlocked messages, those arrive after the browser
......@@ -7565,6 +7568,10 @@ void RenderFrameImpl::UpdateAllLifecyclePhasesAndCompositeForTesting() {
NOTREACHED();
}
void RenderFrameImpl::SetAllowsCrossBrowsingInstanceFrameLookup() {
GetWebFrame()->SetAllowsCrossBrowsingInstanceFrameLookup();
}
#if BUILDFLAG(ENABLE_PLUGINS)
void RenderFrameImpl::PepperInstanceCreated(
PepperPluginInstanceImpl* instance) {
......
......@@ -520,6 +520,7 @@ class CONTENT_EXPORT RenderFrameImpl
void SetRenderFrameMediaPlaybackOptions(
const RenderFrameMediaPlaybackOptions& opts) override;
void UpdateAllLifecyclePhasesAndCompositeForTesting() override;
void SetAllowsCrossBrowsingInstanceFrameLookup() override;
// blink::mojom::AutoplayConfigurationClient implementation:
void AddAutoplayFlags(const url::Origin& origin,
......
......@@ -329,6 +329,16 @@ void ExtensionFrameHelper::ReadyToCommitNavigation(
// TODO(devlin): Add constants for main world id, no extension group.
}
void ExtensionFrameHelper::DidCommitProvisionalLoad(
bool is_same_document_navigation,
ui::PageTransition transition) {
// Grant cross browsing instance frame lookup if we are an extension. This
// should match the conditions in FindFrame.
content::RenderFrame* frame = render_frame();
if (GetExtensionFromFrame(frame))
frame->SetAllowsCrossBrowsingInstanceFrameLookup();
}
void ExtensionFrameHelper::DidCreateScriptContext(
v8::Local<v8::Context> context,
int32_t world_id) {
......
......@@ -125,6 +125,8 @@ class ExtensionFrameHelper
void DidCreateNewDocument() override;
void ReadyToCommitNavigation(
blink::WebDocumentLoader* document_loader) override;
void DidCommitProvisionalLoad(bool is_same_document_navigation,
ui::PageTransition transition) override;
void DidCreateScriptContext(v8::Local<v8::Context>,
int32_t world_id) override;
void WillReleaseScriptContext(v8::Local<v8::Context>,
......
......@@ -767,6 +767,12 @@ class WebLocalFrame : public WebFrame {
virtual void WasHidden() = 0;
virtual void WasShown() = 0;
// Grants ability to lookup a named frame via the FindFrame
// WebLocalFrameClient API. Enhanced binding security checks that check the
// agent cluster will be enabled for windows that do not have this permission.
// This should only be used for extensions and the webview tag.
virtual void SetAllowsCrossBrowsingInstanceFrameLookup() = 0;
protected:
explicit WebLocalFrame(WebTreeScopeType scope) : WebFrame(scope) {}
......
......@@ -2676,4 +2676,17 @@ void WebLocalFrameImpl::WasShown() {
frame_->WasShown();
}
void WebLocalFrameImpl::SetAllowsCrossBrowsingInstanceFrameLookup() {
DCHECK(GetFrame());
// Allow the frame's security origin to access other SecurityOrigins
// that match everything except the agent cluster check. This is needed
// for embedders that hand out frame references outside of a browsing
// instance, for example extensions and webview tag.
GetFrame()
->GetDocument()
->GetMutableSecurityOrigin()
->GrantCrossAgentClusterAccess();
}
} // namespace blink
......@@ -459,6 +459,8 @@ class CORE_EXPORT WebLocalFrameImpl final
virtual void Trace(blink::Visitor*);
void SetAllowsCrossBrowsingInstanceFrameLookup() override;
private:
friend LocalFrameClientImpl;
......
......@@ -22,6 +22,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/frame_client.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
......@@ -289,7 +290,15 @@ Frame* FrameTree::FindFrameForNavigationInternal(const AtomicString& name,
}
// Ask the embedder as a fallback.
return To<LocalFrame>(this_frame_.Get())->Client()->FindFrame(name);
LocalFrame* local_frame = To<LocalFrame>(this_frame_.Get());
Frame* named_frame = local_frame->Client()->FindFrame(name);
// The embedder can return a frame from another agent cluster. Make sure
// that the returned frame, if any, has explicitly allowed cross-agent
// cluster access.
DCHECK(!named_frame || local_frame->GetDocument()
->GetSecurityOrigin()
->IsGrantedCrossAgentClusterAccess());
return named_frame;
}
bool FrameTree::IsDescendantOf(const Frame* ancestor) const {
......
......@@ -173,6 +173,7 @@ SecurityOrigin::SecurityOrigin(const SecurityOrigin* other)
other->block_local_access_from_local_origin_),
is_opaque_origin_potentially_trustworthy_(
other->is_opaque_origin_potentially_trustworthy_),
cross_agent_cluster_access_(other->cross_agent_cluster_access_),
precursor_origin_(other->precursor_origin_
? other->precursor_origin_->IsolatedCopy()
: nullptr) {}
......@@ -486,6 +487,10 @@ void SecurityOrigin::GrantUniversalAccess() {
universal_access_ = true;
}
void SecurityOrigin::GrantCrossAgentClusterAccess() {
cross_agent_cluster_access_ = true;
}
void SecurityOrigin::BlockLocalAccessFromLocalOrigin() {
DCHECK(IsLocal());
block_local_access_from_local_origin_ = true;
......
......@@ -210,6 +210,13 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> {
void GrantUniversalAccess();
bool IsGrantedUniversalAccess() const { return universal_access_; }
// Whether this origin has ability to access another SecurityOrigin
// if everything but the agent clusters do not match.
void GrantCrossAgentClusterAccess();
bool IsGrantedCrossAgentClusterAccess() const {
return cross_agent_cluster_access_;
}
bool CanAccessDatabase() const { return !IsOpaque(); }
bool CanAccessLocalStorage() const { return !IsOpaque(); }
bool CanAccessSharedWorkers() const { return !IsOpaque(); }
......@@ -359,6 +366,7 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> {
bool can_load_local_resources_ = false;
bool block_local_access_from_local_origin_ = false;
bool is_opaque_origin_potentially_trustworthy_ = false;
bool cross_agent_cluster_access_ = false;
// For opaque origins, tracks the non-opaque origin from which the opaque
// origin is derived.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment