Bug 1627963: Remove requestContext from CSP shouldload and replace with fission friendly primitives. r=mattwoodrow

Differential Revision: https://phabricator.services.mozilla.com/D70173

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Christoph Kerschbaumer 2020-04-10 10:56:57 +00:00
parent bb5ca86820
commit 4935907607
11 changed files with 92 additions and 47 deletions

View File

@ -329,11 +329,11 @@ interface nsIContentSecurityPolicy : nsISerializable
short shouldLoad(in nsContentPolicyType aContentType,
in nsICSPEventListener aCSPEventListener,
in nsIURI aContentLocation,
in nsISupports aContext,
in ACString aMimeTypeGuess,
in nsIURI aOriginalURIIfRedirect,
in bool aSendViolationReports,
in AString aNonce);
in AString aNonce,
in boolean aParserCreated);
%{ C++
// nsIObserver topic to fire when the policy encounters a violation.

View File

@ -114,23 +114,23 @@ static void BlockedContentSourceToString(
NS_IMETHODIMP
nsCSPContext::ShouldLoad(nsContentPolicyType aContentType,
nsICSPEventListener* aCSPEventListener,
nsIURI* aContentLocation, nsISupports* aRequestContext,
nsIURI* aContentLocation,
const nsACString& aMimeTypeGuess,
nsIURI* aOriginalURIIfRedirect,
bool aSendViolationReports, const nsAString& aNonce,
int16_t* outDecision) {
bool aParserCreated, int16_t* outDecision) {
return ShouldLoad(AsyncReportViolationCallback(AsyncReportViolation),
aContentType, aCSPEventListener, aContentLocation,
aRequestContext, aMimeTypeGuess, aOriginalURIIfRedirect,
aSendViolationReports, aNonce, outDecision);
aMimeTypeGuess, aOriginalURIIfRedirect,
aSendViolationReports, aNonce, aParserCreated, outDecision);
}
nsresult nsCSPContext::ShouldLoad(
const AsyncReportViolationCallback& aCallback,
nsContentPolicyType aContentType, nsICSPEventListener* aCSPEventListener,
nsIURI* aContentLocation, nsISupports* aRequestContext,
const nsACString& aMimeTypeGuess, nsIURI* aOriginalURIIfRedirect,
bool aSendViolationReports, const nsAString& aNonce, int16_t* outDecision) {
nsIURI* aContentLocation, const nsACString& aMimeTypeGuess,
nsIURI* aOriginalURIIfRedirect, bool aSendViolationReports,
const nsAString& aNonce, bool aParserCreated, int16_t* outDecision) {
if (CSPCONTEXTLOGENABLED()) {
CSPCONTEXTLOG(("nsCSPContext::ShouldLoad, aContentLocation: %s",
aContentLocation->GetSpecOrDefault().get()));
@ -164,14 +164,6 @@ nsresult nsCSPContext::ShouldLoad(
return NS_OK;
}
bool parserCreated = false;
if (!isPreload) {
nsCOMPtr<nsIScriptElement> script = do_QueryInterface(aRequestContext);
if (script && script->GetParserCreated() != mozilla::dom::NOT_FROM_PARSER) {
parserCreated = true;
}
}
bool permitted =
permitsInternal(aCallback, dir,
nullptr, // aTriggeringElement
@ -180,7 +172,7 @@ nsresult nsCSPContext::ShouldLoad(
false, // allow fallback to default-src
aSendViolationReports,
true, // send blocked URI in violation reports
parserCreated);
aParserCreated);
*outDecision =
permitted ? nsIContentPolicy::ACCEPT : nsIContentPolicy::REJECT_SERVER;

View File

@ -156,11 +156,11 @@ class nsCSPContext : public nsIContentSecurityPolicy {
nsresult ShouldLoad(const AsyncReportViolationCallback& aCallback,
nsContentPolicyType aContentType,
nsICSPEventListener* aCSPEventListener,
nsIURI* aContentLocation, nsISupports* aRequestContext,
nsIURI* aContentLocation,
const nsACString& aMimeTypeGuess,
nsIURI* aOriginalURIIfRedirect,
bool aSendViolationReports, const nsAString& aNonce,
int16_t* outDecision);
bool aParserCreated, int16_t* outDecision);
private:
void EnsureIPCPoliciesRead();

View File

@ -103,7 +103,7 @@ bool subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) {
}
uint32_t contentType = aLoadInfo->InternalContentPolicyType();
nsCOMPtr<nsISupports> requestContext = aLoadInfo->GetLoadingContext();
bool parserCreatedScript = aLoadInfo->GetParserCreatedScript();
nsCOMPtr<nsICSPEventListener> cspEventListener;
nsresult rv =
@ -141,10 +141,10 @@ bool subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) {
if (preloadCsp) {
// obtain the enforcement decision
rv = preloadCsp->ShouldLoad(
contentType, cspEventListener, aContentLocation, requestContext,
aMimeTypeGuess,
contentType, cspEventListener, aContentLocation, aMimeTypeGuess,
nullptr, // no redirect, aOriginal URL is null.
aLoadInfo->GetSendCSPViolationEvents(), cspNonce, aDecision);
aLoadInfo->GetSendCSPViolationEvents(), cspNonce, parserCreatedScript,
aDecision);
NS_ENSURE_SUCCESS(rv, rv);
// if the preload policy already denied the load, then there
@ -167,10 +167,10 @@ bool subjectToCSP(nsIURI* aURI, nsContentPolicyType aContentType) {
if (csp) {
// obtain the enforcement decision
rv = csp->ShouldLoad(contentType, cspEventListener, aContentLocation,
requestContext, aMimeTypeGuess,
aMimeTypeGuess,
nullptr, // no redirect, aOriginal URL is null.
aLoadInfo->GetSendCSPViolationEvents(), cspNonce,
aDecision);
parserCreatedScript, aDecision);
if (NS_CP_REJECTED(*aDecision)) {
NS_SetRequestBlockingReason(
@ -335,7 +335,8 @@ nsresult CSPService::ConsultCSPForRedirect(
nsContentUtils::InternalContentPolicyTypeToExternalOrWorker(policyType);
int16_t decision = nsIContentPolicy::ACCEPT;
nsCOMPtr<nsISupports> requestContext = aLoadInfo->GetLoadingContext();
bool parserCreatedScript = aLoadInfo->GetParserCreatedScript();
// 1) Apply speculative CSP for preloads
if (isPreload) {
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp = aLoadInfo->GetPreloadCsp();
@ -346,12 +347,11 @@ nsresult CSPService::ConsultCSPForRedirect(
policyType, // load type per nsIContentPolicy (uint32_t)
cspEventListener,
aNewURI, // nsIURI
requestContext, // nsISupports
EmptyCString(), // ACString - MIME guess
aOriginalURI, // Original nsIURI
true, // aSendViolationReports
cspNonce, // nonce
&decision);
parserCreatedScript, &decision);
// if the preload policy already denied the load, then there
// is no point in checking the real policy
@ -371,12 +371,11 @@ nsresult CSPService::ConsultCSPForRedirect(
policyType, // load type per nsIContentPolicy (uint32_t)
cspEventListener,
aNewURI, // nsIURI
requestContext, // nsISupports
EmptyCString(), // ACString - MIME guess
aOriginalURI, // Original nsIURI
true, // aSendViolationReports
cspNonce, // nonce
&decision);
parserCreatedScript, &decision);
if (NS_CP_REJECTED(decision)) {
aCancelCode = Some(NS_ERROR_DOM_BAD_URI);
return NS_BINDING_FAILED;

View File

@ -183,9 +183,9 @@ function run_test() {
NetUtil.newURI("http://blocked.test/foo.js"),
null,
null,
null,
true,
null
null,
false
);
});
@ -244,9 +244,9 @@ function run_test() {
NetUtil.newURI("data:image/png;base64," + base64data),
null,
null,
null,
true,
null
null,
false
);
});
@ -259,9 +259,9 @@ function run_test() {
NetUtil.newURI("intent://mymaps.com/maps?um=1&ie=UTF-8&fb=1&sll"),
null,
null,
null,
true,
null
null,
false
);
});
@ -276,9 +276,9 @@ function run_test() {
NetUtil.newURI(selfSpec + "#bar"),
null,
null,
null,
true,
null
null,
false
);
});
@ -295,9 +295,9 @@ function run_test() {
NetUtil.newURI("ftp://blocked.test/profile.png"),
null,
null,
null,
true,
null
null,
false
);
}
);

View File

@ -567,6 +567,7 @@ nsresult LoadInfoToLoadInfoArgs(nsILoadInfo* aLoadInfo,
cspNonce, aLoadInfo->GetSkipContentSniffing(),
aLoadInfo->GetHttpsOnlyStatus(),
aLoadInfo->GetAllowDeprecatedSystemRequests(),
aLoadInfo->GetParserCreatedScript(),
aLoadInfo->GetIsFromProcessingFrameAttributes(), cookieJarSettingsArgs,
aLoadInfo->GetRequestBlockingReason(), maybeCspToInheritInfo,
aLoadInfo->GetHasStoragePermission()));
@ -767,8 +768,8 @@ nsresult LoadInfoArgsToLoadInfo(
loadInfoArgs.cspNonce(), loadInfoArgs.skipContentSniffing(),
loadInfoArgs.httpsOnlyStatus(),
loadInfoArgs.allowDeprecatedSystemRequests(),
loadInfoArgs.hasStoragePermission(), loadInfoArgs.requestBlockingReason(),
loadingContext);
loadInfoArgs.parserCreatedScript(), loadInfoArgs.hasStoragePermission(),
loadInfoArgs.requestBlockingReason(), loadingContext);
if (loadInfoArgs.isFromProcessingFrameAttributes()) {
loadInfo->SetIsFromProcessingFrameAttributes();
@ -807,6 +808,7 @@ void LoadInfoToParentLoadInfoForwarder(
aLoadInfo->GetBypassCORSChecks(), ipcController, tainting,
aLoadInfo->GetSkipContentSniffing(), aLoadInfo->GetHttpsOnlyStatus(),
aLoadInfo->GetAllowDeprecatedSystemRequests(),
aLoadInfo->GetParserCreatedScript(),
aLoadInfo->GetServiceWorkerTaintingSynthesized(),
aLoadInfo->GetDocumentHasUserInteracted(),
aLoadInfo->GetDocumentHasLoaded(),
@ -849,6 +851,9 @@ nsresult MergeParentLoadInfoForwarder(
aForwarderArgs.allowDeprecatedSystemRequests());
NS_ENSURE_SUCCESS(rv, rv);
rv = aLoadInfo->SetParserCreatedScript(aForwarderArgs.parserCreatedScript());
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ALWAYS_SUCCEEDS(aLoadInfo->SetDocumentHasUserInteracted(
aForwarderArgs.documentHasUserInteracted()));
MOZ_ALWAYS_SUCCEEDS(

View File

@ -28,6 +28,7 @@
#include "nsIDocShell.h"
#include "mozilla/dom/Document.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIScriptElement.h"
#include "nsISupportsImpl.h"
#include "nsISupportsUtils.h"
#include "nsIXPConnect.h"
@ -104,6 +105,7 @@ LoadInfo::LoadInfo(
mSkipContentSniffing(false),
mHttpsOnlyStatus(nsILoadInfo::HTTPS_ONLY_UNINITIALIZED),
mAllowDeprecatedSystemRequests(false),
mParserCreatedScript(false),
mHasStoragePermission(false),
mIsFromProcessingFrameAttributes(false) {
MOZ_ASSERT(mLoadingPrincipal);
@ -319,6 +321,15 @@ LoadInfo::LoadInfo(
}
}
}
// in case this is a loadinfo for a parser generated script, then we store
// that bit of information so CSP strict-dynamic can query it.
if (!nsContentUtils::IsPreloadType(mInternalContentPolicyType)) {
nsCOMPtr<nsIScriptElement> script = do_QueryInterface(aLoadingContext);
if (script && script->GetParserCreated() != mozilla::dom::NOT_FROM_PARSER) {
mParserCreatedScript = true;
}
}
}
/* Constructor takes an outer window, but no loadingNode or loadingPrincipal.
@ -369,6 +380,7 @@ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
mSkipContentSniffing(false),
mHttpsOnlyStatus(nsILoadInfo::HTTPS_ONLY_UNINITIALIZED),
mAllowDeprecatedSystemRequests(false),
mParserCreatedScript(false),
mHasStoragePermission(false),
mIsFromProcessingFrameAttributes(false) {
// Top-level loads are never third-party
@ -472,6 +484,7 @@ LoadInfo::LoadInfo(dom::CanonicalBrowsingContext* aBrowsingContext,
mSkipContentSniffing(false),
mHttpsOnlyStatus(nsILoadInfo::HTTPS_ONLY_UNINITIALIZED),
mAllowDeprecatedSystemRequests(false),
mParserCreatedScript(false),
mHasStoragePermission(false),
mIsFromProcessingFrameAttributes(false) {
// Top-level loads are never third-party
@ -575,6 +588,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
mSkipContentSniffing(rhs.mSkipContentSniffing),
mHttpsOnlyStatus(rhs.mHttpsOnlyStatus),
mAllowDeprecatedSystemRequests(rhs.mAllowDeprecatedSystemRequests),
mParserCreatedScript(rhs.mParserCreatedScript),
mHasStoragePermission(rhs.mHasStoragePermission),
mIsFromProcessingFrameAttributes(rhs.mIsFromProcessingFrameAttributes) {}
@ -614,8 +628,8 @@ LoadInfo::LoadInfo(
bool aAllowListFutureDocumentsCreatedFromThisRedirectChain,
const nsAString& aCspNonce, bool aSkipContentSniffing,
uint32_t aHttpsOnlyStatus, bool aAllowDeprecatedSystemRequests,
bool aHasStoragePermission, uint32_t aRequestBlockingReason,
nsINode* aLoadingContext)
bool aParserCreatedScript, bool aHasStoragePermission,
uint32_t aRequestBlockingReason, nsINode* aLoadingContext)
: mLoadingPrincipal(aLoadingPrincipal),
mTriggeringPrincipal(aTriggeringPrincipal),
mPrincipalToInherit(aPrincipalToInherit),
@ -673,6 +687,7 @@ LoadInfo::LoadInfo(
mSkipContentSniffing(aSkipContentSniffing),
mHttpsOnlyStatus(aHttpsOnlyStatus),
mAllowDeprecatedSystemRequests(aAllowDeprecatedSystemRequests),
mParserCreatedScript(aParserCreatedScript),
mHasStoragePermission(aHasStoragePermission),
mIsFromProcessingFrameAttributes(false) {
// Only top level TYPE_DOCUMENT loads can have a null loadingPrincipal
@ -1519,6 +1534,18 @@ LoadInfo::SetAllowDeprecatedSystemRequests(
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetParserCreatedScript(bool* aParserCreatedScript) {
*aParserCreatedScript = mParserCreatedScript;
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::SetParserCreatedScript(bool aParserCreatedScript) {
mParserCreatedScript = aParserCreatedScript;
return NS_OK;
}
NS_IMETHODIMP
LoadInfo::GetIsTopLevelLoad(bool* aResult) {
*aResult = mFrameOuterWindowID ? mFrameOuterWindowID == mOuterWindowID

View File

@ -164,8 +164,8 @@ class LoadInfo final : public nsILoadInfo {
bool aAllowListFutureDocumentsCreatedFromThisRedirectChain,
const nsAString& aCspNonce, bool aSkipContentSniffing,
uint32_t aHttpsOnlyStatus, bool aAllowDeprecatedSystemRequests,
bool aHasStoragePermission, uint32_t aRequestBlockingReason,
nsINode* aLoadingContext);
bool aParserCreatedScript, bool aHasStoragePermission,
uint32_t aRequestBlockingReason, nsINode* aLoadingContext);
LoadInfo(const LoadInfo& rhs);
NS_IMETHOD GetRedirects(JSContext* aCx,
@ -262,6 +262,7 @@ class LoadInfo final : public nsILoadInfo {
bool mSkipContentSniffing;
uint32_t mHttpsOnlyStatus;
bool mAllowDeprecatedSystemRequests;
bool mParserCreatedScript;
bool mHasStoragePermission;
// Is true if this load was triggered by processing the attributes of the

View File

@ -624,5 +624,15 @@ TRRLoadInfo::SetAllowDeprecatedSystemRequests(
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
TRRLoadInfo::GetParserCreatedScript(bool* aParserCreatedScript) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
TRRLoadInfo::SetParserCreatedScript(bool aParserCreatedScript) {
return NS_ERROR_NOT_IMPLEMENTED;
}
} // namespace net
} // namespace mozilla

View File

@ -463,6 +463,12 @@ interface nsILoadInfo : nsISupports
*/
[infallible] attribute boolean allowDeprecatedSystemRequests;
/**
* Only ever returns true if the loadinfo is of TYPE_SCRIPT and
* the script was created by the HTML parser.
*/
[infallible] attribute boolean parserCreatedScript;
/**
* True if this request is embedded in a context that can't be third-party
* (i.e. an iframe embedded in a cross-origin parent window). If this is

View File

@ -147,6 +147,7 @@ struct LoadInfoArgs
bool skipContentSniffing;
uint32_t httpsOnlyStatus;
bool allowDeprecatedSystemRequests;
bool parserCreatedScript;
bool isFromProcessingFrameAttributes;
CookieJarSettingsArgs cookieJarSettings;
uint32_t requestBlockingReason;
@ -193,6 +194,10 @@ struct ParentLoadInfoForwarderArgs
// the request from being cancelled.
bool allowDeprecatedSystemRequests;
// Only ever returns true if the loadinfo is of TYPE_SCRIPT and
// the script was created by the HTML parser.
bool parserCreatedScript;
// We must also note that the tainting value was explicitly set
// by the service worker.
bool serviceWorkerTaintingSynthesized;