Bug 1626404: Part 1 - Move IsSandboxedFrom to BrowsingContext. r=nika CLOSED TREE

Differential Revision: https://phabricator.services.mozilla.com/D69417
This commit is contained in:
Kris Maglione
2020-04-04 02:42:30 +00:00
parent 058a273a3a
commit 35503e3f6f
5 changed files with 70 additions and 75 deletions

View File

@@ -43,6 +43,7 @@
#include "nsGlobalWindowOuter.h"
#include "nsIObserverService.h"
#include "nsContentUtils.h"
#include "nsSandboxFlags.h"
#include "nsScriptError.h"
#include "nsThreadUtils.h"
#include "xpcprivate.h"
@@ -889,6 +890,61 @@ bool BrowsingContext::CanAccess(BrowsingContext* aTarget,
return false;
}
bool BrowsingContext::IsSandboxedFrom(BrowsingContext* aTarget) {
// If no target then not sandboxed.
if (!aTarget) {
return false;
}
// We cannot be sandboxed from ourselves.
if (aTarget == this) {
return false;
}
// Default the sandbox flags to our flags, so that if we can't retrieve the
// active document, we will still enforce our own.
uint32_t sandboxFlags = GetSandboxFlags();
if (mDocShell) {
if (RefPtr<Document> doc = mDocShell->GetExtantDocument()) {
sandboxFlags = doc->GetSandboxFlags();
}
}
// If no flags, we are not sandboxed at all.
if (!sandboxFlags) {
return false;
}
// If aTarget has an ancestor, it is not top level.
if (RefPtr<BrowsingContext> ancestorOfTarget = aTarget->GetParent()) {
do {
// We are not sandboxed if we are an ancestor of target.
if (ancestorOfTarget == this) {
return false;
}
ancestorOfTarget = ancestorOfTarget->GetParent();
} while (ancestorOfTarget);
// Otherwise, we are sandboxed from aTarget.
return true;
}
// aTarget is top level, are we the "one permitted sandboxed
// navigator", i.e. did we open aTarget?
if (aTarget->GetOnePermittedSandboxedNavigatorId() == Id()) {
return false;
}
// If SANDBOXED_TOPLEVEL_NAVIGATION flag is not on, we are not sandboxed
// from our top.
if (!(sandboxFlags & SANDBOXED_TOPLEVEL_NAVIGATION) && aTarget == Top()) {
return false;
}
// Otherwise, we are sandboxed from aTarget.
return true;
}
RefPtr<SessionStorageManager> BrowsingContext::GetSessionStorageManager() {
RefPtr<SessionStorageManager>& manager = Top()->mSessionStorageManager;
if (!manager) {

View File

@@ -538,6 +538,8 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
// Performs access control to check that 'this' can access 'aTarget'.
bool CanAccess(BrowsingContext* aTarget, bool aConsiderOpener = true);
bool IsSandboxedFrom(BrowsingContext* aTarget);
// The runnable will be called once there is idle time, or the top level
// page has been loaded or if a timeout has fired.
// Must be called only on the top level BrowsingContext.

View File

@@ -2731,66 +2731,6 @@ nsDocShell::GetSameTypeRootTreeItemIgnoreBrowserBoundaries(
return NS_OK;
}
bool nsDocShell::IsSandboxedFrom(BrowsingContext* aTargetBC) {
// If no target then not sandboxed.
if (!aTargetBC) {
return false;
}
// We cannot be sandboxed from ourselves.
if (aTargetBC == mBrowsingContext) {
return false;
}
// Default the sandbox flags to our flags, so that if we can't retrieve the
// active document, we will still enforce our own.
uint32_t sandboxFlags = mBrowsingContext->GetSandboxFlags();
if (mContentViewer) {
RefPtr<Document> doc = mContentViewer->GetDocument();
if (doc) {
sandboxFlags = doc->GetSandboxFlags();
}
}
// If no flags, we are not sandboxed at all.
if (!sandboxFlags) {
return false;
}
// If aTargetBC has an ancestor, it is not top level.
RefPtr<BrowsingContext> ancestorOfTarget(aTargetBC->GetParent());
if (ancestorOfTarget) {
do {
// We are not sandboxed if we are an ancestor of target.
if (ancestorOfTarget == mBrowsingContext) {
return false;
}
ancestorOfTarget = ancestorOfTarget->GetParent();
} while (ancestorOfTarget);
// Otherwise, we are sandboxed from aTargetBC.
return true;
}
// aTargetBC is top level, are we the "one permitted sandboxed
// navigator", i.e. did we open aTargetBC?
RefPtr<BrowsingContext> permittedNavigator(
aTargetBC->GetOnePermittedSandboxedNavigator());
if (permittedNavigator == mBrowsingContext) {
return false;
}
// If SANDBOXED_TOPLEVEL_NAVIGATION flag is not on, we are not sandboxed
// from our top.
if (!(sandboxFlags & SANDBOXED_TOPLEVEL_NAVIGATION) &&
aTargetBC == mBrowsingContext->Top()) {
return false;
}
// Otherwise, we are sandboxed from aTargetBC.
return true;
}
NS_IMETHODIMP
nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner) {
NS_ENSURE_ARG_POINTER(aTreeOwner);
@@ -3199,6 +3139,10 @@ Document* nsDocShell::GetDocument() {
return mContentViewer->GetDocument();
}
Document* nsDocShell::GetExtantDocument() {
return mContentViewer ? mContentViewer->GetDocument() : nullptr;
}
nsPIDOMWindowOuter* nsDocShell::GetWindow() {
if (NS_FAILED(EnsureScriptEnvironment())) {
return nullptr;
@@ -8787,7 +8731,8 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
// If a source docshell has been passed, check to see if we are sandboxed
// from it as the result of an iframe or CSP sandbox.
if (aLoadState->SourceDocShell() &&
aLoadState->SourceDocShell()->IsSandboxedFrom(mBrowsingContext)) {
aLoadState->SourceDocShell()->GetBrowsingContext()->IsSandboxedFrom(
mBrowsingContext)) {
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
}

View File

@@ -737,12 +737,6 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
readonly attribute bool asyncPanZoomEnabled;
/**
* Returns true if we are sandboxed from aTargetDocShell.
* aTargetDocShell - the browsing context we are attempting to navigate.
*/
[noscript,notxpcom,nostdcall] bool isSandboxedFrom(in BrowsingContext aTargetBC);
/**
* This member variable determines whether a document has Mixed Active Content that
* was initially blocked from loading, but the user has choosen to override the
@@ -881,6 +875,8 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
[noscript,notxpcom,nostdcall] nsIScriptGlobalObject GetScriptGlobalObject();
[noscript,notxpcom,nostdcall] Document getExtantDocument();
/**
* If deviceSizeIsPageSize is set to true, device-width/height media queries
* will be calculated from the page size, not the device size.

View File

@@ -653,6 +653,8 @@ nsresult nsWindowWatcher::OpenWindowInternal(
RefPtr<BrowsingContext> parentBC(
parentWindow ? parentWindow->GetBrowsingContext() : nullptr);
nsCOMPtr<nsIDocShell> parentDocShell(parentBC ? parentBC->GetDocShell()
: nullptr);
// Return null for any attempt to trigger a load from a discarded browsing
// context. The spec is non-normative, and doesn't specify what should happen
@@ -673,15 +675,9 @@ nsresult nsWindowWatcher::OpenWindowInternal(
// Do sandbox checks here, instead of waiting until nsIDocShell::LoadURI.
// The state of the window can change before this call and if we are blocked
// because of sandboxing, we wouldn't want that to happen.
nsCOMPtr<nsIDocShell> parentDocShell;
if (parentWindow) {
parentDocShell = parentWindow->GetDocShell();
if (parentDocShell) {
if (parentDocShell->IsSandboxedFrom(newBC)) {
if (parentBC && parentBC->IsSandboxedFrom(newBC)) {
return NS_ERROR_DOM_INVALID_ACCESS_ERR;
}
}
}
// no extant window? make a new one.