Bug 1729640 - P1. Extend AddHighValuePermission to support 'highValueHasSavedLogin' and 'highValueIsLoggedIn' permission. r=necko-reviewers,farre,kershaw

This patch:
1. adds two 'highValueHasSavedLogin' and 'highValueIsLoggedIn' permission
2. moves 'AddHighValuePermission' from HttpBaseChannel to ProcessIsolation
   to support more high-value permission type.

Differential Revision: https://phabricator.services.mozilla.com/D127101
This commit is contained in:
Dimi 2021-11-05 17:11:31 +00:00
parent 82fcbdc4b5
commit 56505f3e46
3 changed files with 76 additions and 50 deletions

View File

@ -460,6 +460,8 @@ static bool ShouldIsolateSite(nsIPrincipal* aPrincipal,
static constexpr nsLiteralCString kHighValuePermissions[] = {
mozilla::dom::kHighValueCOOPPermission,
mozilla::dom::kHighValueHasSavedLoginPermission,
mozilla::dom::kHighValueIsLoggedInPermission,
};
for (const auto& type : kHighValuePermissions) {
@ -907,4 +909,50 @@ Result<NavigationIsolationOptions, nsresult> IsolationOptionsForNavigation(
return options;
}
void AddHighValuePermission(nsIPrincipal* aResultPrincipal,
const nsACString& aPermissionType) {
RefPtr<PermissionManager> perms = PermissionManager::GetInstance();
if (NS_WARN_IF(!perms)) {
return;
}
// We can't act on non-content principals, so if the load was sandboxed, try
// to use the unsandboxed precursor principal to add the highValue permission.
nsCOMPtr<nsIPrincipal> resultOrPrecursor(aResultPrincipal);
if (!aResultPrincipal->GetIsContentPrincipal()) {
resultOrPrecursor = aResultPrincipal->GetPrecursorPrincipal();
if (!resultOrPrecursor) {
return;
}
}
// Use the site-origin principal as we want to add the permission for the
// entire site, rather than a specific subdomain, as process isolation acts on
// a site granularity.
nsAutoCString siteOrigin;
if (NS_FAILED(resultOrPrecursor->GetSiteOrigin(siteOrigin))) {
return;
}
nsCOMPtr<nsIPrincipal> sitePrincipal =
BasePrincipal::CreateContentPrincipal(siteOrigin);
if (!sitePrincipal || !sitePrincipal->GetIsContentPrincipal()) {
return;
}
MOZ_LOG(dom::gProcessIsolationLog, LogLevel::Verbose,
("Adding HighValue COOP Permission for site '%s'", siteOrigin.get()));
// XXX: Would be nice if we could use `TimeStamp` here, but there's
// unfortunately no convenient way to recover a time in milliseconds since the
// unix epoch from `TimeStamp`.
int64_t expirationTime =
(PR_Now() / PR_USEC_PER_MSEC) +
(int64_t(StaticPrefs::fission_highValue_coop_expiration()) *
PR_MSEC_PER_SEC);
Unused << perms->AddFromPrincipal(
sitePrincipal, aPermissionType, nsIPermissionManager::ALLOW_ACTION,
nsIPermissionManager::EXPIRE_TIME, expirationTime);
}
} // namespace mozilla::dom

View File

@ -25,6 +25,10 @@ class WindowGlobalParent;
extern mozilla::LazyLogModule gProcessIsolationLog;
constexpr nsLiteralCString kHighValueCOOPPermission = "highValueCOOP"_ns;
constexpr nsLiteralCString kHighValueHasSavedLoginPermission =
"highValueHasSavedLogin"_ns;
constexpr nsLiteralCString kHighValueIsLoggedInPermission =
"highValueIsLoggedIn"_ns;
// NavigationIsolationOptions is passed through the methods to store the state
// of the possible process and/or browsing context change.
@ -55,6 +59,27 @@ Result<NavigationIsolationOptions, nsresult> IsolationOptionsForNavigation(
uint32_t aLoadStateLoadType, const Maybe<uint64_t>& aChannelId,
const Maybe<nsCString>& aRemoteTypeOverride);
/**
* Adds a `highValue` permission to the permissions database, and make loads of
* that origin isolated.
*
* The 'aPermissionType' parameter indicates why the site is treated as a high
* value site. The possible values are:
*
* kHighValueCOOPPermission
* Called when a document request responds with a
* `Cross-Origin-Opener-Policy` header.
*
* kHighValueHasSavedLoginPermission
* Called for sites that have an associated login saved in the password
* manager.
*
* kHighValueIsLoggedInPermission
* Called when we detect a form with a password is submitted.
*/
void AddHighValuePermission(nsIPrincipal* aResultPrincipal,
const nsACString& aPermissionType);
} // namespace mozilla::dom
#endif

View File

@ -36,6 +36,7 @@
#include "mozilla/dom/nsHTTPSOnlyUtils.h"
#include "mozilla/dom/Performance.h"
#include "mozilla/dom/PerformanceStorage.h"
#include "mozilla/dom/ProcessIsolation.h"
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/net/OpaqueResponseUtils.h"
#include "mozilla/net/PartiallySeekableInputStream.h"
@ -2310,55 +2311,6 @@ nsresult HttpBaseChannel::ProcessCrossOriginResourcePolicyHeader() {
return NS_OK;
}
// Called when a document request responds with a `Cross-Origin-Opener-Policy`
// header to add a `highValueCOOP` permission to the permissions database, and
// make loads of that origin isolated.
static void AddHighValueCOOPPermission(nsIPrincipal* aResultPrincipal) {
RefPtr<PermissionManager> perms = PermissionManager::GetInstance();
if (NS_WARN_IF(!perms)) {
return;
}
// We can't act on non-content principals, so if the load was sandboxed, try
// to use the unsandboxed precursor principal to add the highValueCOOP
// permission.
nsCOMPtr<nsIPrincipal> resultOrPrecursor(aResultPrincipal);
if (!aResultPrincipal->GetIsContentPrincipal()) {
resultOrPrecursor = aResultPrincipal->GetPrecursorPrincipal();
if (!resultOrPrecursor) {
return;
}
}
// Use the site-origin principal as we want to add the permission for the
// entire site, rather than a specific subdomain, as process isolation acts on
// a site granularity.
nsAutoCString siteOrigin;
if (NS_FAILED(resultOrPrecursor->GetSiteOrigin(siteOrigin))) {
return;
}
nsCOMPtr<nsIPrincipal> sitePrincipal =
BasePrincipal::CreateContentPrincipal(siteOrigin);
if (!sitePrincipal || !sitePrincipal->GetIsContentPrincipal()) {
return;
}
MOZ_LOG(dom::gProcessIsolationLog, LogLevel::Verbose,
("Adding HighValue COOP Permission for site '%s'", siteOrigin.get()));
// XXX: Would be nice if we could use `TimeStamp` here, but there's
// unfortunately no convenient way to recover a time in milliseconds since the
// unix epoch from `TimeStamp`.
int64_t expirationTime =
(PR_Now() / PR_USEC_PER_MSEC) +
(int64_t(StaticPrefs::fission_highValue_coop_expiration()) *
PR_MSEC_PER_SEC);
Unused << perms->AddFromPrincipal(
sitePrincipal, mozilla::dom::kHighValueCOOPPermission,
nsIPermissionManager::ALLOW_ACTION, nsIPermissionManager::EXPIRE_TIME,
expirationTime);
}
// See https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
// This method runs steps 1-4 of the algorithm to compare
@ -2429,7 +2381,8 @@ nsresult HttpBaseChannel::ComputeCrossOriginOpenerPolicyMismatch() {
// Add a permission to mark this site as high-value into the permission DB.
if (resultPolicy != nsILoadInfo::OPENER_POLICY_UNSAFE_NONE) {
AddHighValueCOOPPermission(resultOrigin);
mozilla::dom::AddHighValuePermission(
resultOrigin, mozilla::dom::kHighValueCOOPPermission);
}
// If bc's popup sandboxing flag set is not empty and potentialCOOP is