Bug 1834786 - Don't return cached stylesheets if the sheet principal doesn't match. r=dholbert

Otherwise stuff accessing stylesheets from a sandbox and content might
conflict, and we might incorrectly deny giving access to a CSSStyleSheet's
rules.

Differential Revision: https://phabricator.services.mozilla.com/D178971
This commit is contained in:
Emilio Cobos Álvarez 2023-05-28 20:43:32 +00:00
parent 2d68c1a7db
commit 216d1c4ccc
4 changed files with 30 additions and 27 deletions

View File

@ -1688,18 +1688,25 @@ void Loader::MarkLoadTreeFailed(SheetLoadData& aLoadData,
} while (data);
}
RefPtr<StyleSheet> Loader::LookupInlineSheetInCache(const nsAString& aBuffer) {
RefPtr<StyleSheet> Loader::LookupInlineSheetInCache(
const nsAString& aBuffer, nsIPrincipal* aSheetPrincipal) {
auto result = mInlineSheets.Lookup(aBuffer);
if (!result) {
return nullptr;
}
if (result.Data()->HasModifiedRules()) {
StyleSheet* sheet = result.Data();
if (NS_WARN_IF(sheet->HasModifiedRules())) {
// Remove it now that we know that we're never going to use this stylesheet
// again.
result.Remove();
return nullptr;
}
return result.Data()->Clone(nullptr, nullptr);
if (NS_WARN_IF(!sheet->Principal()->Equals(aSheetPrincipal))) {
// If the sheet is going to have different access rights, don't return it
// from the cache.
return nullptr;
}
return sheet->Clone(nullptr, nullptr);
}
void Loader::MaybeNotifyPreloadUsed(SheetLoadData& aData) {
@ -1748,11 +1755,23 @@ Result<Loader::LoadSheetResult, nsresult> Loader::LoadInlineStyle(
nsIURI* originalURI = nullptr;
MOZ_ASSERT(aInfo.mIntegrity.IsEmpty());
nsIPrincipal* loadingPrincipal = LoaderPrincipal();
nsIPrincipal* principal = aInfo.mTriggeringPrincipal
? aInfo.mTriggeringPrincipal.get()
: loadingPrincipal;
nsIPrincipal* sheetPrincipal = [&] {
// The triggering principal may be an expanded principal, which is safe to
// use for URL security checks, but not as the loader principal for a
// stylesheet. So treat this as principal inheritance, and downgrade if
// necessary.
//
// FIXME(emilio): Why doing this for inline sheets but not for links?
if (aInfo.mTriggeringPrincipal) {
return BasePrincipal::Cast(aInfo.mTriggeringPrincipal)
->PrincipalToInherit();
}
return LoaderPrincipal();
}();
// We only cache sheets if in shadow trees, since regular document sheets are
// likely to be unique.
@ -1761,7 +1780,7 @@ Result<Loader::LoadSheetResult, nsresult> Loader::LoadInlineStyle(
aInfo.mContent->IsInShadowTree();
RefPtr<StyleSheet> sheet;
if (isWorthCaching) {
sheet = LookupInlineSheetInCache(aBuffer);
sheet = LookupInlineSheetInCache(aBuffer, sheetPrincipal);
}
const bool sheetFromCache = !!sheet;
if (!sheet) {
@ -1771,18 +1790,7 @@ Result<Loader::LoadSheetResult, nsresult> Loader::LoadInlineStyle(
nsIReferrerInfo* referrerInfo =
aInfo.mContent->OwnerDoc()->ReferrerInfoForInternalCSSAndSVGResources();
sheet->SetReferrerInfo(referrerInfo);
nsIPrincipal* sheetPrincipal = principal;
if (aInfo.mTriggeringPrincipal) {
// The triggering principal may be an expanded principal, which is safe to
// use for URL security checks, but not as the loader principal for a
// stylesheet. So treat this as principal inheritance, and downgrade if
// necessary.
sheetPrincipal =
BasePrincipal::Cast(aInfo.mTriggeringPrincipal)->PrincipalToInherit();
}
// We never actually load this, so just set its principal directly
// We never actually load this, so just set its principal directly.
sheet->SetPrincipal(sheetPrincipal);
}

View File

@ -544,7 +544,7 @@ class Loader final {
CORSMode aCORSMode, const nsAString& aIntegrity,
uint64_t aEarlyHintPreloaderId);
RefPtr<StyleSheet> LookupInlineSheetInCache(const nsAString&);
RefPtr<StyleSheet> LookupInlineSheetInCache(const nsAString&, nsIPrincipal*);
// Post a load event for aObserver to be notified about aSheet. The
// notification will be sent with status NS_OK unless the load event is

View File

@ -366,12 +366,7 @@ StyleSheetInfo::StyleSheetInfo(CORSMode aCORSMode,
mReferrerInfo(new ReferrerInfo(nullptr)),
mIntegrity(aIntegrity),
mContents(Servo_StyleSheet_Empty(aParsingMode).Consume()),
mURLData(URLExtraData::Dummy())
#ifdef DEBUG
,
mPrincipalSet(false)
#endif
{
mURLData(URLExtraData::Dummy()) {
if (!mPrincipal) {
MOZ_CRASH("NullPrincipal::Init failed");
}

View File

@ -26,7 +26,7 @@ struct URLExtraData;
* Struct for data common to CSSStyleSheetInner and ServoStyleSheet.
*/
struct StyleSheetInfo final {
typedef dom::ReferrerPolicy ReferrerPolicy;
using ReferrerPolicy = dom::ReferrerPolicy;
StyleSheetInfo(CORSMode aCORSMode, const dom::SRIMetadata& aIntegrity,
css::SheetParsingMode aParsingMode);
@ -49,7 +49,7 @@ struct StyleSheetInfo final {
nsCOMPtr<nsIURI> mOriginalSheetURI; // for GetHref. Can be null.
nsCOMPtr<nsIURI> mBaseURI; // for resolving relative URIs
nsCOMPtr<nsIPrincipal> mPrincipal;
CORSMode mCORSMode;
const CORSMode mCORSMode;
// The ReferrerInfo of a stylesheet is used for its child sheets and loads
// come from this stylesheet, so it is stored here.
nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
@ -91,7 +91,7 @@ struct StyleSheetInfo final {
RefPtr<URLExtraData> mURLData;
#ifdef DEBUG
bool mPrincipalSet;
bool mPrincipalSet = false;
#endif
};