зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1570738 - Record Telemetry if eval() is used in the Parent Process r=ckerschb
Differential Revision: https://phabricator.services.mozilla.com/D40332 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
4a8f79932f
Коммит
20c32a0175
|
@ -500,9 +500,10 @@ pref("browser.tabs.remote.enforceRemoteTypeRestrictions", true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NIGHTLY_BUILD
|
#ifdef NIGHTLY_BUILD
|
||||||
// allow_eval_with_system_principal is enabled on Firefox Desktop only at this
|
// allow_eval_* is enabled on Firefox Desktop only at this
|
||||||
// point in time
|
// point in time
|
||||||
pref("security.allow_eval_with_system_principal", false);
|
pref("security.allow_eval_with_system_principal", false);
|
||||||
|
pref("security.allow_eval_in_parent_process", false);
|
||||||
pref("browser.tabs.remote.useHTTPResponseProcessSelection", true);
|
pref("browser.tabs.remote.useHTTPResponseProcessSelection", true);
|
||||||
#else
|
#else
|
||||||
// Disabled outside of nightly due to bug 1554217
|
// Disabled outside of nightly due to bug 1554217
|
||||||
|
|
|
@ -424,11 +424,12 @@ bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
|
||||||
nsresult rv = csp->GetAllowsEval(&reportViolation, &evalOK);
|
nsresult rv = csp->GetAllowsEval(&reportViolation, &evalOK);
|
||||||
|
|
||||||
// A little convoluted. We want the scriptSample for a) reporting a violation
|
// A little convoluted. We want the scriptSample for a) reporting a violation
|
||||||
// or b) passing it to AssertEvalNotUsingSystemPrincipal. So do the work to
|
// or b) passing it to AssertEvalNotUsingSystemPrincipal or c) we're in the
|
||||||
// get it if either of those cases is true.
|
// parent process. So do the work to get it if either of those cases is true.
|
||||||
nsAutoJSString scriptSample;
|
nsAutoJSString scriptSample;
|
||||||
nsCOMPtr<nsIPrincipal> subjectPrincipal = nsContentUtils::SubjectPrincipal();
|
nsCOMPtr<nsIPrincipal> subjectPrincipal = nsContentUtils::SubjectPrincipal();
|
||||||
if (reportViolation || subjectPrincipal->IsSystemPrincipal()) {
|
if (reportViolation || subjectPrincipal->IsSystemPrincipal() ||
|
||||||
|
XRE_IsE10sParentProcess()) {
|
||||||
JS::Rooted<JSString*> jsString(cx, JS::ToString(cx, aValue));
|
JS::Rooted<JSString*> jsString(cx, JS::ToString(cx, aValue));
|
||||||
if (NS_WARN_IF(!jsString)) {
|
if (NS_WARN_IF(!jsString)) {
|
||||||
JS_ClearPendingException(cx);
|
JS_ClearPendingException(cx);
|
||||||
|
@ -442,8 +443,8 @@ bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(ANDROID) && (defined(NIGHTLY_BUILD) || defined(DEBUG))
|
#if !defined(ANDROID) && (defined(NIGHTLY_BUILD) || defined(DEBUG))
|
||||||
nsContentSecurityManager::AssertEvalNotUsingSystemPrincipal(
|
nsContentSecurityManager::AssertEvalNotRestricted(cx, subjectPrincipal,
|
||||||
cx, subjectPrincipal, scriptSample);
|
scriptSample);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
|
|
|
@ -33,8 +33,8 @@ nsresult CheckInternal(nsIContentSecurityPolicy* aCSP,
|
||||||
|
|
||||||
#if !defined(ANDROID) && (defined(NIGHTLY_BUILD) || defined(DEBUG))
|
#if !defined(ANDROID) && (defined(NIGHTLY_BUILD) || defined(DEBUG))
|
||||||
JSContext* cx = nsContentUtils::GetCurrentJSContext();
|
JSContext* cx = nsContentUtils::GetCurrentJSContext();
|
||||||
nsContentSecurityManager::AssertEvalNotUsingSystemPrincipal(
|
nsContentSecurityManager::AssertEvalNotRestricted(cx, aSubjectPrincipal,
|
||||||
cx, aSubjectPrincipal, aExpression);
|
aExpression);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The value is set at any "return", but better to have a default value here.
|
// The value is set at any "return", but better to have a default value here.
|
||||||
|
|
|
@ -71,6 +71,8 @@ static NS_NAMED_LITERAL_STRING(sAllowedEval1, "this");
|
||||||
static NS_NAMED_LITERAL_STRING(sAllowedEval2,
|
static NS_NAMED_LITERAL_STRING(sAllowedEval2,
|
||||||
"function anonymous(\n) {\nreturn this\n}");
|
"function anonymous(\n) {\nreturn this\n}");
|
||||||
|
|
||||||
|
static Atomic<bool, mozilla::Relaxed> sTelemetryEventEnabled(false);
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
bool nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
|
bool nsContentSecurityManager::AllowTopLevelNavigationToDataURI(
|
||||||
nsIChannel* aChannel) {
|
nsIChannel* aChannel) {
|
||||||
|
@ -384,20 +386,32 @@ FilenameType nsContentSecurityManager::FilenameToEvalType(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
void nsContentSecurityManager::AssertEvalNotUsingSystemPrincipal(
|
void nsContentSecurityManager::AssertEvalNotRestricted(
|
||||||
JSContext* cx, nsIPrincipal* aSubjectPrincipal, const nsAString& aScript) {
|
JSContext* cx, nsIPrincipal* aSubjectPrincipal, const nsAString& aScript) {
|
||||||
if (!aSubjectPrincipal->IsSystemPrincipal()) {
|
bool systemPrincipal = aSubjectPrincipal->IsSystemPrincipal();
|
||||||
|
if (systemPrincipal &&
|
||||||
|
StaticPrefs::security_allow_eval_with_system_principal()) {
|
||||||
|
MOZ_LOG(
|
||||||
|
sCSMLog, LogLevel::Debug,
|
||||||
|
("Allowing eval() %s because allowing pref is "
|
||||||
|
"enabled",
|
||||||
|
(systemPrincipal ? "with System Principal" : "in parent process")));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use static pref for performance reasons.
|
if (XRE_IsE10sParentProcess() &&
|
||||||
if (StaticPrefs::security_allow_eval_with_system_principal()) {
|
StaticPrefs::security_allow_eval_in_parent_process()) {
|
||||||
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
||||||
("Allowing eval() with SystemPrincipal because allowing pref is "
|
("Allowing eval() in parent process because allowing pref is "
|
||||||
"enabled"));
|
"enabled"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!systemPrincipal && !XRE_IsE10sParentProcess()) {
|
||||||
|
// Usage of eval we are unconcerned with.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// This preferences is a file used for autoconfiguration of Firefox
|
// This preferences is a file used for autoconfiguration of Firefox
|
||||||
// by administrators. It has also been (ab)used by the userChromeJS
|
// by administrators. It has also been (ab)used by the userChromeJS
|
||||||
// project to run legacy-style 'extensions', some of which use eval,
|
// project to run legacy-style 'extensions', some of which use eval,
|
||||||
|
@ -405,22 +419,28 @@ void nsContentSecurityManager::AssertEvalNotUsingSystemPrincipal(
|
||||||
nsAutoString configPref;
|
nsAutoString configPref;
|
||||||
Preferences::GetString("general.config.filename", configPref);
|
Preferences::GetString("general.config.filename", configPref);
|
||||||
if (!configPref.IsEmpty()) {
|
if (!configPref.IsEmpty()) {
|
||||||
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
MOZ_LOG(
|
||||||
("Allowing eval() with SystemPrincipal because of "
|
sCSMLog, LogLevel::Debug,
|
||||||
"general.config.filename"));
|
("Allowing eval() %s because of "
|
||||||
|
"general.config.filename",
|
||||||
|
(systemPrincipal ? "with System Principal" : "in parent process")));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We permit these two common idioms to get access to the global JS object
|
// We permit these two common idioms to get access to the global JS object
|
||||||
if (!aScript.IsEmpty() &&
|
if (!aScript.IsEmpty() &&
|
||||||
(aScript == sAllowedEval1 || aScript == sAllowedEval2)) {
|
(aScript == sAllowedEval1 || aScript == sAllowedEval2)) {
|
||||||
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
MOZ_LOG(
|
||||||
("Allowing eval() with SystemPrincipal because a key string is "
|
sCSMLog, LogLevel::Debug,
|
||||||
"provided"));
|
("Allowing eval() %s because a key string is "
|
||||||
|
"provided",
|
||||||
|
(systemPrincipal ? "with System Principal" : "in parent process")));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoCString fileName;
|
// Check the allowlist for the provided filename. getFilename is a helper
|
||||||
|
// function
|
||||||
|
auto getFilename = [](JSContext* cx) -> const nsCString {
|
||||||
JS::AutoFilename scriptFilename;
|
JS::AutoFilename scriptFilename;
|
||||||
if (JS::DescribeScriptedCaller(cx, &scriptFilename)) {
|
if (JS::DescribeScriptedCaller(cx, &scriptFilename)) {
|
||||||
nsDependentCSubstring fileName_(scriptFilename.get(),
|
nsDependentCSubstring fileName_(scriptFilename.get(),
|
||||||
|
@ -433,14 +453,28 @@ void nsContentSecurityManager::AssertEvalNotUsingSystemPrincipal(
|
||||||
fileName_.SetLength(fileNameIndex);
|
fileName_.SetLength(fileNameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsAutoCString fileName(fileName_);
|
||||||
|
return std::move(fileName);
|
||||||
|
}
|
||||||
|
return NS_LITERAL_CSTRING("unknown-file");
|
||||||
|
};
|
||||||
|
|
||||||
|
nsCString fileName = getFilename(cx);
|
||||||
for (const nsLiteralCString& allowlistEntry : evalAllowlist) {
|
for (const nsLiteralCString& allowlistEntry : evalAllowlist) {
|
||||||
if (fileName_.Equals(allowlistEntry)) {
|
if (fileName.Equals(allowlistEntry)) {
|
||||||
|
MOZ_LOG(
|
||||||
|
sCSMLog, LogLevel::Debug,
|
||||||
|
("Allowing eval() %s because the containing "
|
||||||
|
"file is in the allowlist",
|
||||||
|
(systemPrincipal ? "with System Principal" : "in parent process")));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileName = fileName_;
|
// Send Telemetry
|
||||||
}
|
Telemetry::EventID eventType =
|
||||||
|
systemPrincipal ? Telemetry::EventID::Security_Evalusage_Systemcontext
|
||||||
|
: Telemetry::EventID::Security_Evalusage_Parentprocess;
|
||||||
|
|
||||||
FilenameType fileNameType =
|
FilenameType fileNameType =
|
||||||
FilenameToEvalType(NS_ConvertUTF8toUTF16(fileName));
|
FilenameToEvalType(NS_ConvertUTF8toUTF16(fileName));
|
||||||
|
@ -452,18 +486,25 @@ void nsContentSecurityManager::AssertEvalNotUsingSystemPrincipal(
|
||||||
} else {
|
} else {
|
||||||
extra = Nothing();
|
extra = Nothing();
|
||||||
}
|
}
|
||||||
Telemetry::RecordEvent(Telemetry::EventID::Security_Evalusage_Systemcontext,
|
if (!sTelemetryEventEnabled.exchange(true)) {
|
||||||
mozilla::Some(fileNameType.first()), extra);
|
sTelemetryEventEnabled = true;
|
||||||
|
Telemetry::SetEventRecordingEnabled(
|
||||||
|
NS_LITERAL_CSTRING("security.evalUsage"), true);
|
||||||
|
}
|
||||||
|
Telemetry::RecordEvent(eventType, mozilla::Some(fileNameType.first()), extra);
|
||||||
|
|
||||||
|
// Crash or Log
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
MOZ_CRASH_UNSAFE_PRINTF(
|
MOZ_CRASH_UNSAFE_PRINTF(
|
||||||
"Blocking eval() with SystemPrincipal from file %s and script provided "
|
"Blocking eval() %s from file %s and script provided "
|
||||||
"%s",
|
"%s",
|
||||||
|
(systemPrincipal ? "with System Principal" : "in parent process"),
|
||||||
fileName.get(), NS_ConvertUTF16toUTF8(aScript).get());
|
fileName.get(), NS_ConvertUTF16toUTF8(aScript).get());
|
||||||
#else
|
#else
|
||||||
MOZ_LOG(sCSMLog, LogLevel::Debug,
|
MOZ_LOG(sCSMLog, LogLevel::Warning,
|
||||||
("Blocking eval() with SystemPrincipal from file %s and script "
|
("Blocking eval() %s from file %s and script "
|
||||||
"provided %s",
|
"provided %s",
|
||||||
|
(systemPrincipal ? "with System Principal" : "in parent process"),
|
||||||
fileName.get(), NS_ConvertUTF16toUTF8(aScript).get()));
|
fileName.get(), NS_ConvertUTF16toUTF8(aScript).get()));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ class nsContentSecurityManager : public nsIContentSecurityManager,
|
||||||
static bool AllowInsecureRedirectToDataURI(nsIChannel* aNewChannel);
|
static bool AllowInsecureRedirectToDataURI(nsIChannel* aNewChannel);
|
||||||
|
|
||||||
static FilenameType FilenameToEvalType(const nsString& fileName);
|
static FilenameType FilenameToEvalType(const nsString& fileName);
|
||||||
static void AssertEvalNotUsingSystemPrincipal(JSContext* cx,
|
static void AssertEvalNotRestricted(JSContext* cx,
|
||||||
nsIPrincipal* aSubjectPrincipal,
|
nsIPrincipal* aSubjectPrincipal,
|
||||||
const nsAString& aScript);
|
const nsAString& aScript);
|
||||||
|
|
||||||
|
|
|
@ -5971,6 +5971,13 @@
|
||||||
value: true
|
value: true
|
||||||
mirror: always
|
mirror: always
|
||||||
|
|
||||||
|
# Disabled by default so it doesn't affect Thunderbird/SeaMonkey, but
|
||||||
|
# enabled in firefox.js
|
||||||
|
- name: security.allow_eval_in_parent_process
|
||||||
|
type: bool
|
||||||
|
value: true
|
||||||
|
mirror: always
|
||||||
|
|
||||||
# Whether strict file origin policy is in effect.
|
# Whether strict file origin policy is in effect.
|
||||||
- name: security.fileuri.strict_origin_policy
|
- name: security.fileuri.strict_origin_policy
|
||||||
type: RelaxedAtomicBool
|
type: RelaxedAtomicBool
|
||||||
|
|
|
@ -1593,11 +1593,12 @@ intl.ui.browserLanguage:
|
||||||
|
|
||||||
security:
|
security:
|
||||||
evalUsage:
|
evalUsage:
|
||||||
objects: ["systemContext"]
|
objects: ["systemContext", "parentProcess"]
|
||||||
bug_numbers:
|
bug_numbers:
|
||||||
- 1567623
|
- 1567623
|
||||||
description: >
|
description: >
|
||||||
eval() (or an eval()-like method) was called while running in the System Principal Context.
|
eval() (or an eval()-like method) was called while running in the System Principal
|
||||||
|
context or the Parent Process.
|
||||||
Expected values are:
|
Expected values are:
|
||||||
chromeuri - chrome:// file
|
chromeuri - chrome:// file
|
||||||
resourceuri - resource:// file
|
resourceuri - resource:// file
|
||||||
|
|
Загрузка…
Ссылка в новой задаче