Bug 1834864 - Select BCG more consistently during COOP+COEP process switches, r=smaug,tabbrowser-reviewers,mak

Previously it was possible to bypass specific BCG selection based on
cross-origin isolated status if the site was allowed to load file URIs
using enterprise policies, which could lead to a crash.

This patch changes the behaviour such that BCG selection now happens
correctly. The site will still not be cross-origin isolated due to being
loaded into a file content process.

Differential Revision: https://phabricator.services.mozilla.com/D217007
This commit is contained in:
Nika Layzell
2024-07-19 14:38:20 +00:00
parent 971159e0a1
commit 0c56f81d86
7 changed files with 93 additions and 30 deletions

View File

@@ -202,6 +202,10 @@ skip-if = ["verify && os == 'mac'"]
["browser_new_file_whitelisted_http_tab.js"] ["browser_new_file_whitelisted_http_tab.js"]
https_first_disabled = true https_first_disabled = true
support-files = [
"file_coop_coep.html",
"file_coop_coep.html^headers^",
]
["browser_new_tab_bookmarks_toolbar_height.js"] ["browser_new_tab_bookmarks_toolbar_height.js"]
skip-if = ["!verify && os == 'mac'"] # Bug 1872477 skip-if = ["!verify && os == 'mac'"] # Bug 1872477

View File

@@ -1,8 +1,15 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
// eslint-disable-next-line @microsoft/sdl/no-insecure-url const TEST_HTTP_DOMAIN = "https://example.org/";
const TEST_HTTP = "http://example.org/";
const TEST_ROOT = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
"https://example.org"
);
const TEST_NORMAL = `${TEST_ROOT}dummy_page.html`;
const TEST_COOP_COEP = `${TEST_ROOT}file_coop_coep.html`;
// Test for bug 1378377. // Test for bug 1378377.
add_task(async function () { add_task(async function () {
@@ -11,27 +18,72 @@ add_task(async function () {
set: [["browser.tabs.remote.separateFileUriProcess", true]], set: [["browser.tabs.remote.separateFileUriProcess", true]],
}); });
await BrowserTestUtils.withNewTab(TEST_HTTP, async function (fileBrowser) { await BrowserTestUtils.withNewTab(TEST_NORMAL, async function (fileBrowser) {
ok( ok(
E10SUtils.isWebRemoteType(fileBrowser.remoteType), E10SUtils.isWebRemoteType(fileBrowser.remoteType),
"Check that tab normally has web remote type." "Check that tab normally has web remote type."
); );
await SpecialPowers.spawn(fileBrowser, [], () => {
ok(
!content.crossOriginIsolated,
"Tab content is not cross-origin isolated"
);
});
}); });
await BrowserTestUtils.withNewTab(
TEST_COOP_COEP,
async function (fileBrowser) {
ok(
fileBrowser.remoteType.startsWith(
E10SUtils.WEB_REMOTE_COOP_COEP_TYPE_PREFIX
),
"Check that COOP+COEP tab normally has webCOOP+COEP remote type."
);
await SpecialPowers.spawn(fileBrowser, [], () => {
ok(content.crossOriginIsolated, "Tab content is cross-origin isolated");
});
}
);
// Set prefs to whitelist TEST_HTTP for file:// URI use. // Set prefs to whitelist TEST_HTTP for file:// URI use.
await SpecialPowers.pushPrefEnv({ await SpecialPowers.pushPrefEnv({
set: [ set: [
["capability.policy.policynames", "allowFileURI"], ["capability.policy.policynames", "allowFileURI"],
["capability.policy.allowFileURI.sites", TEST_HTTP], ["capability.policy.allowFileURI.sites", TEST_HTTP_DOMAIN],
["capability.policy.allowFileURI.checkloaduri.enabled", "allAccess"], ["capability.policy.allowFileURI.checkloaduri.enabled", "allAccess"],
], ],
}); });
await BrowserTestUtils.withNewTab(TEST_HTTP, async function (fileBrowser) { await BrowserTestUtils.withNewTab(TEST_NORMAL, async function (fileBrowser) {
is( is(
fileBrowser.remoteType, fileBrowser.remoteType,
E10SUtils.FILE_REMOTE_TYPE, E10SUtils.FILE_REMOTE_TYPE,
"Check that tab now has file remote type." "Check that tab now has file remote type."
); );
await SpecialPowers.spawn(fileBrowser, [], () => {
ok(
!content.crossOriginIsolated,
"Tab content is not cross-origin isolated"
);
});
}); });
await BrowserTestUtils.withNewTab(
TEST_COOP_COEP,
async function (fileBrowser) {
is(
fileBrowser.remoteType,
E10SUtils.FILE_REMOTE_TYPE,
"Check that tab now has file remote type."
);
await SpecialPowers.spawn(fileBrowser, [], () => {
ok(
!content.crossOriginIsolated,
"Tab content is not cross-origin isolated"
);
});
}
);
}); });

View File

@@ -0,0 +1 @@
<!DOCTYPE html>

View File

@@ -0,0 +1,2 @@
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

View File

@@ -2172,11 +2172,13 @@ CanonicalBrowsingContext::ChangeRemoteness(
new PendingRemotenessChange(this, promise, aPendingSwitchId, aOptions); new PendingRemotenessChange(this, promise, aPendingSwitchId, aOptions);
mPendingRemotenessChange = change; mPendingRemotenessChange = change;
// If a specific BrowsingContextGroup ID was specified for this load, make // If we're replacing BrowsingContext, determine which BrowsingContextGroup
// sure to keep it alive until the process switch is completed. // we'll switch into, taking into account load options.
if (aOptions.mSpecificGroupId) { if (aOptions.mReplaceBrowsingContext) {
change->mSpecificGroup = change->mSpecificGroup =
BrowsingContextGroup::GetOrCreate(aOptions.mSpecificGroupId); aOptions.mSpecificGroupId
? BrowsingContextGroup::GetOrCreate(aOptions.mSpecificGroupId)
: BrowsingContextGroup::Create(aOptions.mShouldCrossOriginIsolate);
change->mSpecificGroup->AddKeepAlive(); change->mSpecificGroup->AddKeepAlive();
} }

View File

@@ -418,6 +418,24 @@ static already_AddRefed<BasePrincipal> GetAboutReaderURLPrincipal(
return nullptr; return nullptr;
} }
/**
* Check the Cross-Origin-Opener-Policy of the given channel or ancestor
* BrowsingContext, checking if the response should be cross-origin isolated.
*/
static bool ShouldCrossOriginIsolate(nsIChannel* aChannel,
WindowGlobalParent* aParentWindow) {
nsILoadInfo::CrossOriginOpenerPolicy coop =
nsILoadInfo::OPENER_POLICY_UNSAFE_NONE;
if (aParentWindow) {
coop = aParentWindow->BrowsingContext()->Top()->GetOpenerPolicy();
} else if (nsCOMPtr<nsIHttpChannelInternal> httpChannel =
do_QueryInterface(aChannel)) {
MOZ_ALWAYS_SUCCEEDS(httpChannel->GetCrossOriginOpenerPolicy(&coop));
}
return coop ==
nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP;
}
/** /**
* Returns `true` if loads for this site should be isolated on a per-site basis. * Returns `true` if loads for this site should be isolated on a per-site basis.
* If `aTopBC` is nullptr, this is being called to check if a shared or service * If `aTopBC` is nullptr, this is being called to check if a shared or service
@@ -580,6 +598,8 @@ Result<NavigationIsolationOptions, nsresult> IsolationOptionsForNavigation(
NavigationIsolationOptions options; NavigationIsolationOptions options;
options.mReplaceBrowsingContext = aHasCOOPMismatch; options.mReplaceBrowsingContext = aHasCOOPMismatch;
options.mShouldCrossOriginIsolate =
ShouldCrossOriginIsolate(aChannel, aParentWindow);
// Check if this load has an explicit remote type override. This is used to // Check if this load has an explicit remote type override. This is used to
// perform an about:blank load within a specific content process. // perform an about:blank load within a specific content process.
@@ -871,28 +891,9 @@ Result<NavigationIsolationOptions, nsresult> IsolationOptionsForNavigation(
webProcessType = WebProcessType::WebIsolated; webProcessType = WebProcessType::WebIsolated;
} }
// Check if we should be loading in a webCOOP+COEP remote type due to our COOP // Check if we should be cross-origin isolated.
// status. if (options.mShouldCrossOriginIsolate) {
nsILoadInfo::CrossOriginOpenerPolicy coop =
nsILoadInfo::OPENER_POLICY_UNSAFE_NONE;
if (aParentWindow) {
coop = aTopBC->GetOpenerPolicy();
} else if (nsCOMPtr<nsIHttpChannelInternal> httpChannel =
do_QueryInterface(aChannel)) {
MOZ_ALWAYS_SUCCEEDS(httpChannel->GetCrossOriginOpenerPolicy(&coop));
}
if (coop ==
nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) {
webProcessType = WebProcessType::WebCoopCoep; webProcessType = WebProcessType::WebCoopCoep;
// If we're changing BrowsingContext, and are going to end up within a
// webCOOP+COEP group, ensure we use a cross-origin isolated BCG ID.
if (options.mReplaceBrowsingContext) {
MOZ_ASSERT(!options.mSpecificGroupId,
"overriding previously-specified BCG ID");
options.mSpecificGroupId = BrowsingContextGroup::CreateId(
/* aPotentiallyCrossOriginIsolated */ true);
}
} }
switch (webProcessType) { switch (webProcessType) {

View File

@@ -36,6 +36,7 @@ struct NavigationIsolationOptions {
nsCString mRemoteType; nsCString mRemoteType;
bool mReplaceBrowsingContext = false; bool mReplaceBrowsingContext = false;
uint64_t mSpecificGroupId = 0; uint64_t mSpecificGroupId = 0;
bool mShouldCrossOriginIsolate = false;
bool mTryUseBFCache = false; bool mTryUseBFCache = false;
RefPtr<SessionHistoryEntry> mActiveSessionHistoryEntry; RefPtr<SessionHistoryEntry> mActiveSessionHistoryEntry;
}; };