Skip to content

Commit

Permalink
Bug 1905239 - Add new parameters to HostEnsureCanCompileStrings hook.…
Browse files Browse the repository at this point in the history
… r=tschuster

Currently, we do this via isRuntimeCodeGenEnabled whose single argument
is equivalent to codeString in "Dynamic Code Brand Checks" spec [1]. We
extend this hook to accept new parameters from that spec and adjust
PerformEval and CreateDynamicFunction accordingly. We don't change the
behavior for PerformShadowRealmEval [2] and WASM, i.e. we keep dummy
parameters.

[1] https://tc39.es/proposal-dynamic-code-brand-checks
[2] tc39/proposal-shadowrealm#414

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

UltraBlame original commit: 2baefcde5dbc41852c85e4f7198b338e529b7406
  • Loading branch information
marco-c committed Dec 13, 2024
1 parent 3b25a69 commit dbe417f
Show file tree
Hide file tree
Showing 12 changed files with 363 additions and 33 deletions.
24 changes: 17 additions & 7 deletions caps/nsScriptSecurityManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
#include "nsJSUtils.h"
#include "nsILoadInfo.h"
#include "js/ColumnNumber.h"
#include "js/GCVector.h"
#include "js/Value.h"


#define WEBAPPS_PERM_NAME "webapps-manage"
Expand Down Expand Up @@ -462,7 +464,12 @@ NS_IMPL_ISUPPORTS(nsScriptSecurityManager, nsIScriptSecurityManager)


bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
JSContext* cx, JS::RuntimeCode aKind, JS::Handle<JSString*> aCode) {
JSContext* cx, JS::RuntimeCode aKind, JS::Handle<JSString*> aCodeString,
JS::CompilationType aCompilationType,
JS::Handle<JS::StackGCVector<JSString*>> aParameterStrings,
JS::Handle<JSString*> aBodyString,
JS::Handle<JS::StackGCVector<JS::Value>> aParameterArgs,
JS::Handle<JS::Value> aBodyArg, bool* aOutCanCompileStrings) {
MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());

nsCOMPtr<nsIPrincipal> subjectPrincipal = nsContentUtils::SubjectPrincipal();
Expand All @@ -477,13 +484,14 @@ bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
if (contextForbidsEval) {
nsAutoJSString scriptSample;
if (aKind == JS::RuntimeCode::JS &&
NS_WARN_IF(!scriptSample.init(cx, aCode))) {
NS_WARN_IF(!scriptSample.init(cx, aCodeString))) {
return false;
}

if (!nsContentSecurityUtils::IsEvalAllowed(
cx, subjectPrincipal->IsSystemPrincipal(), scriptSample)) {
return false;
*aOutCanCompileStrings = false;
return true;
}
}

Expand All @@ -503,6 +511,7 @@ bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
}

if (!csp) {
*aOutCanCompileStrings = true;
return true;
}
}
Expand All @@ -522,7 +531,8 @@ bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
nsresult rv = csp->GetAllowsEval(&reportViolation, &evalOK);
if (NS_FAILED(rv)) {
NS_WARNING("CSP: failed to get allowsEval");
return true;
*aOutCanCompileStrings = true;
return true;
}
} else {
if (NS_FAILED(csp->GetAllowsWasmEval(&reportViolation, &evalOK))) {
Expand All @@ -545,8 +555,7 @@ bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
auto caller = JSCallingLocation::Get(cx);
nsAutoJSString scriptSample;
if (aKind == JS::RuntimeCode::JS &&
NS_WARN_IF(!scriptSample.init(cx, aCode))) {
JS_ClearPendingException(cx);
NS_WARN_IF(!scriptSample.init(cx, aCodeString))) {
return false;
}
uint16_t violationType =
Expand All @@ -559,7 +568,8 @@ bool nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(
caller.mLine, caller.mColumn, u""_ns, u""_ns);
}

return evalOK;
*aOutCanCompileStrings = evalOK;
return true;
}


Expand Down
11 changes: 8 additions & 3 deletions caps/nsScriptSecurityManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class SystemPrincipal;

namespace JS {
enum class RuntimeCode;
enum class CompilationType;
}


Expand Down Expand Up @@ -91,9 +92,13 @@ class nsScriptSecurityManager final : public nsIScriptSecurityManager {
virtual ~nsScriptSecurityManager();


static bool ContentSecurityPolicyPermitsJSAction(JSContext* cx,
JS::RuntimeCode kind,
JS::Handle<JSString*> aCode);
static bool ContentSecurityPolicyPermitsJSAction(
JSContext* aCx, JS::RuntimeCode aKind, JS::Handle<JSString*> aCodeString,
JS::CompilationType aCompilationType,
JS::Handle<JS::StackGCVector<JSString*>> aParameterStrings,
JS::Handle<JSString*> aBodyString,
JS::Handle<JS::StackGCVector<JS::Value>> aParameterArgs,
JS::Handle<JS::Value> aBodyArg, bool* aOutCanCompileStrings);

static bool JSPrincipalsSubsume(JSPrincipals* first, JSPrincipals* second);

Expand Down
20 changes: 14 additions & 6 deletions dom/workers/RuntimeService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@
#include "jsfriendapi.h"
#include "js/friend/ErrorMessages.h"
#include "js/ContextOptions.h"
#include "js/GCVector.h"
#include "js/Initialization.h"
#include "js/LocaleSensitive.h"
#include "js/Value.h"
#include "js/WasmFeatures.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Atomics.h"
Expand Down Expand Up @@ -499,8 +501,13 @@ class LogViolationDetailsRunnable final : public WorkerMainThreadRunnable {
~LogViolationDetailsRunnable() = default;
};

bool ContentSecurityPolicyAllows(JSContext* aCx, JS::RuntimeCode aKind,
JS::Handle<JSString*> aCode) {
bool ContentSecurityPolicyAllows(
JSContext* aCx, JS::RuntimeCode aKind, JS::Handle<JSString*> aCodeString,
JS::CompilationType aCompilationType,
JS::Handle<JS::StackGCVector<JSString*>> aParameterStrings,
JS::Handle<JSString*> aBodyString,
JS::Handle<JS::StackGCVector<JS::Value>> aParameterArgs,
JS::Handle<JS::Value> aBodyArg, bool* aOutCanCompileStrings) {
WorkerPrivate* worker = GetWorkerPrivateFromContext(aCx);
worker->AssertIsOnWorkerThread();

Expand All @@ -509,14 +516,14 @@ bool ContentSecurityPolicyAllows(JSContext* aCx, JS::RuntimeCode aKind,
uint16_t violationType;
nsAutoJSString scriptSample;
if (aKind == JS::RuntimeCode::JS) {
if (NS_WARN_IF(!scriptSample.init(aCx, aCode))) {
JS_ClearPendingException(aCx);
if (NS_WARN_IF(!scriptSample.init(aCx, aCodeString))) {
return false;
}

if (!nsContentSecurityUtils::IsEvalAllowed(
aCx, worker->UsesSystemPrincipal(), scriptSample)) {
return false;
*aOutCanCompileStrings = false;
return true;
}

evalOK = worker->IsEvalAllowed();
Expand All @@ -542,7 +549,8 @@ bool ContentSecurityPolicyAllows(JSContext* aCx, JS::RuntimeCode aKind,
}
}

return evalOK;
*aOutCanCompileStrings = evalOK;
return true;
}

void CTypesActivityCallback(JSContext* aCx, JS::CTypesActivityType aType) {
Expand Down
19 changes: 17 additions & 2 deletions js/public/Principals.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ typedef bool (*JSSubsumesOp)(JSPrincipals* first, JSPrincipals* second);

namespace JS {
enum class RuntimeCode { JS, WASM };
enum class CompilationType { DirectEval, IndirectEval, Function, Undefined };
}


Expand All @@ -89,8 +90,22 @@ enum class RuntimeCode { JS, WASM };



typedef bool (*JSCSPEvalChecker)(JSContext* cx, JS::RuntimeCode kind,
JS::HandleString code);









typedef bool (*JSCSPEvalChecker)(
JSContext* cx, JS::RuntimeCode kind, JS::Handle<JSString*> codeString,
JS::CompilationType compilationType,
JS::Handle<JS::StackGCVector<JSString*>> parameterStrings,
JS::Handle<JSString*> bodyString,
JS::Handle<JS::StackGCVector<JS::Value>> parameterArgs,
JS::Handle<JS::Value> bodyArg, bool* outCanCompileStrings);



Expand Down
12 changes: 11 additions & 1 deletion js/src/builtin/Eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,17 @@ static bool EvalKernel(JSContext* cx, HandleValue v, EvalType evalType,
}


if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::JS, str)) {
JS::RootedVector<JSString*> parameterStrings(cx);
JS::RootedVector<Value> parameterArgs(cx);
bool canCompileStrings = false;
if (!cx->isRuntimeCodeGenEnabled(
JS::RuntimeCode::JS, str,
evalType == DIRECT_EVAL ? JS::CompilationType::DirectEval
: JS::CompilationType::IndirectEval,
parameterStrings, str, parameterArgs, v, &canCompileStrings)) {
return false;
}
if (!canCompileStrings) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_CSP_BLOCKED_EVAL);
return false;
Expand Down
11 changes: 10 additions & 1 deletion js/src/builtin/ShadowRealm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,16 @@ static bool PerformShadowRealmEval(JSContext* cx, Handle<JSString*> sourceText,
MOZ_ASSERT(callerRealm != evalRealm);


if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::JS, sourceText)) {
JS::RootedVector<JSString*> parameterStrings(cx);
JS::RootedVector<Value> parameterArgs(cx);
bool canCompileStrings = false;
if (!cx->isRuntimeCodeGenEnabled(JS::RuntimeCode::JS, sourceText,
JS::CompilationType::Undefined,
parameterStrings, nullptr, parameterArgs,
NullHandleValue, &canCompileStrings)) {
return false;
}
if (!canCompileStrings) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_CSP_BLOCKED_SHADOWREALM);
return false;
Expand Down
Loading

0 comments on commit dbe417f

Please sign in to comment.