Bug 1461938 part 20 - Move principals and isSystem from JSCompartment to JS::Realm. r=luke

This commit is contained in:
Jan de Mooij 2018-05-23 11:04:27 +02:00
parent 126fa176e1
commit e8626c8f07
17 changed files with 117 additions and 115 deletions

View File

@ -1369,7 +1369,7 @@ CaptureFirstSubsumedFrame(JSContext* cx, unsigned argc, JS::Value* vp)
return false;
}
JS::StackCapture capture(JS::FirstSubsumedFrame(cx, obj->compartment()->principals()));
JS::StackCapture capture(JS::FirstSubsumedFrame(cx, obj->realm()->principals()));
if (args.length() > 1)
capture.as<JS::FirstSubsumedFrame>().ignoreSelfHosted = JS::ToBoolean(args[1]);

View File

@ -752,7 +752,7 @@ TokenStreamAnyChars::fillExcludingContext(ErrorMetadata* err, uint32_t offset)
if (!filename_ && !cx->helperThread()) {
NonBuiltinFrameIter iter(cx,
FrameIter::FOLLOW_DEBUGGER_EVAL_PREV_LINK,
cx->compartment()->principals());
cx->realm()->principals());
if (!iter.done() && iter.filename()) {
err->filename = iter.filename();
err->lineNumber = iter.computeLine(&err->columnNumber);

View File

@ -4065,7 +4065,7 @@ JS::CompileOptions::CompileOptions(JSContext* cx)
{
strictOption = cx->options().strictMode();
extraWarningsOption = cx->realm()->behaviors().extraWarnings(cx);
isProbablySystemCode = cx->compartment()->isProbablySystemCode();
isProbablySystemCode = cx->realm()->isProbablySystemCode();
werrorOption = cx->options().werror();
if (!cx->options().asmJS())
asmJSOption = AsmJSOption::Disabled;
@ -7513,7 +7513,7 @@ DescribeScriptedCaller(JSContext* cx, AutoFilename* filename, unsigned* lineno,
if (!cx->compartment())
return false;
NonBuiltinFrameIter i(cx, cx->compartment()->principals());
NonBuiltinFrameIter i(cx, cx->realm()->principals());
if (i.done())
return false;
@ -7787,7 +7787,7 @@ JS::SetOutOfMemoryCallback(JSContext* cx, OutOfMemoryCallback cb, void* data)
JS::FirstSubsumedFrame::FirstSubsumedFrame(JSContext* cx,
bool ignoreSelfHostedFrames /* = true */)
: JS::FirstSubsumedFrame(cx, cx->compartment()->principals(), ignoreSelfHostedFrames)
: JS::FirstSubsumedFrame(cx, cx->realm()->principals(), ignoreSelfHostedFrames)
{ }
JS_PUBLIC_API(bool)

View File

@ -446,7 +446,7 @@ Error(JSContext* cx, unsigned argc, Value* vp)
}
/* Find the scripted caller, but only ones we're allowed to know about. */
NonBuiltinFrameIter iter(cx, cx->compartment()->principals());
NonBuiltinFrameIter iter(cx, cx->realm()->principals());
/* Set the 'fileName' property. */
RootedString fileName(cx);
@ -967,7 +967,7 @@ ErrorReport::populateUncaughtExceptionReportUTF8VA(JSContext* cx, va_list ap)
// XXXbz this assumes the stack we have right now is still
// related to our exception object. It would be better if we
// could accept a passed-in stack of some sort instead.
NonBuiltinFrameIter iter(cx, cx->compartment()->principals());
NonBuiltinFrameIter iter(cx, cx->realm()->principals());
if (!iter.done()) {
ownedReport.filename = iter.filename();
uint32_t column;

View File

@ -155,40 +155,42 @@ JS_GetIsSecureContext(JSCompartment* compartment)
JS_FRIEND_API(JSPrincipals*)
JS_GetCompartmentPrincipals(JSCompartment* compartment)
{
return compartment->principals();
Realm* realm = JS::GetRealmForCompartment(compartment);
return realm->principals();
}
JS_FRIEND_API(void)
JS_SetCompartmentPrincipals(JSCompartment* compartment, JSPrincipals* principals)
{
// Short circuit if there's no change.
if (principals == compartment->principals())
Realm* realm = JS::GetRealmForCompartment(compartment);
if (principals == realm->principals())
return;
// Any compartment with the trusted principals -- and there can be
// multiple -- is a system compartment.
const JSPrincipals* trusted = compartment->runtimeFromMainThread()->trustedPrincipals();
// Any realm with the trusted principals -- and there can be
// multiple -- is a system realm.
const JSPrincipals* trusted = realm->runtimeFromMainThread()->trustedPrincipals();
bool isSystem = principals && principals == trusted;
// Clear out the old principals, if any.
if (compartment->principals()) {
JS_DropPrincipals(TlsContext.get(), compartment->principals());
compartment->setPrincipals(nullptr);
if (realm->principals()) {
JS_DropPrincipals(TlsContext.get(), realm->principals());
realm->setPrincipals(nullptr);
// We'd like to assert that our new principals is always same-origin
// with the old one, but JSPrincipals doesn't give us a way to do that.
// But we can at least assert that we're not switching between system
// and non-system.
MOZ_ASSERT(compartment->isSystem() == isSystem);
MOZ_ASSERT(realm->isSystem() == isSystem);
}
// Set up the new principals.
if (principals) {
JS_HoldPrincipals(principals);
compartment->setPrincipals(principals);
realm->setPrincipals(principals);
}
// Update the system flag.
compartment->setIsSystem(isSystem);
realm->setIsSystem(isSystem);
}
JS_FRIEND_API(JSPrincipals*)
@ -333,7 +335,7 @@ js::GetCompartmentZone(JSCompartment* comp)
JS_FRIEND_API(bool)
js::IsSystemCompartment(JSCompartment* comp)
{
return comp->isSystem();
return JS::GetRealmForCompartment(comp)->isSystem();
}
JS_FRIEND_API(bool)

View File

@ -383,7 +383,7 @@ js::RunScript(JSContext* cx, RunState& state)
// Since any script can conceivably GC, make sure it's safe to do so.
cx->verifyIsSafeToGC();
MOZ_DIAGNOSTIC_ASSERT(cx->compartment()->isSystem() ||
MOZ_DIAGNOSTIC_ASSERT(cx->realm()->isSystem() ||
cx->runtime()->allowContentJS());
MOZ_ASSERT(!cx->enableAccessValidation ||

View File

@ -44,8 +44,6 @@ using mozilla::PodArrayZero;
JSCompartment::JSCompartment(Zone* zone)
: zone_(zone),
runtime_(zone->runtimeFromAnyThread()),
principals_(nullptr),
isSystem_(false),
isSelfHosting(false),
performanceMonitoring(runtime_),
data(nullptr),

View File

@ -555,56 +555,6 @@ struct JSCompartment
JS::Zone* zone_;
JSRuntime* runtime_;
public:
/*
* The principals associated with this compartment. Note that the
* same several compartments may share the same principals and
* that a compartment may change principals during its lifetime
* (e.g. in case of lazy parsing).
*/
inline JSPrincipals* principals() {
return principals_;
}
inline void setPrincipals(JSPrincipals* principals) {
if (principals_ == principals)
return;
// If we change principals, we need to unlink immediately this
// compartment from its PerformanceGroup. For one thing, the
// performance data we collect should not be improperly associated
// with a group to which we do not belong anymore. For another thing,
// we use `principals()` as part of the key to map compartments
// to a `PerformanceGroup`, so if we do not unlink now, this will
// be too late once we have updated `principals_`.
performanceMonitoring.unlink();
principals_ = principals;
}
inline bool isSystem() const {
return isSystem_;
}
inline void setIsSystem(bool isSystem) {
if (isSystem_ == isSystem)
return;
// If we change `isSystem*(`, we need to unlink immediately this
// compartment from its PerformanceGroup. For one thing, the
// performance data we collect should not be improperly associated
// to a group to which we do not belong anymore. For another thing,
// we use `isSystem()` as part of the key to map compartments
// to a `PerformanceGroup`, so if we do not unlink now, this will
// be too late once we have updated `isSystem_`.
performanceMonitoring.unlink();
isSystem_ = isSystem;
}
// Used to approximate non-content code when reporting telemetry.
inline bool isProbablySystemCode() const {
return isSystem_;
}
private:
JSPrincipals* principals_;
bool isSystem_;
public:
bool isSelfHosting;
@ -1027,6 +977,8 @@ class JS::Realm : public JSCompartment
friend class js::AutoSetNewObjectMetadata;
js::NewObjectMetadataState objectMetadataState_ { js::ImmediateMetadata() };
JSPrincipals* principals_ = nullptr;
// Used by memory reporters and invalid otherwise.
JS::RealmStats* realmStats_ = nullptr;
@ -1037,6 +989,7 @@ class JS::Realm : public JSCompartment
bool isAtomsRealm_ = false;
bool marked_ = true;
bool isSystem_ = false;
public:
// WebAssembly state for the realm.
@ -1228,6 +1181,51 @@ class JS::Realm : public JSCompartment
void unmark() {
marked_ = false;
}
/*
* The principals associated with this realm. Note that the same several
* realms may share the same principals and that a realm may change
* principals during its lifetime (e.g. in case of lazy parsing).
*/
JSPrincipals* principals() {
return principals_;
}
void setPrincipals(JSPrincipals* principals) {
if (principals_ == principals)
return;
// If we change principals, we need to unlink immediately this
// realm from its PerformanceGroup. For one thing, the performance data
// we collect should not be improperly associated with a group to which
// we do not belong anymore. For another thing, we use `principals()` as
// part of the key to map realms to a `PerformanceGroup`, so if we do
// not unlink now, this will be too late once we have updated
// `principals_`.
performanceMonitoring.unlink();
principals_ = principals;
}
bool isSystem() const {
return isSystem_;
}
void setIsSystem(bool isSystem) {
if (isSystem_ == isSystem)
return;
// If we change `isSystem*(`, we need to unlink immediately this realm
// from its PerformanceGroup. For one thing, the performance data we
// collect should not be improperly associated to a group to which we
// do not belong anymore. For another thing, we use `isSystem()` as part
// of the key to map realms to a `PerformanceGroup`, so if we do not
// unlink now, this will be too late once we have updated `isSystem_`.
performanceMonitoring.unlink();
isSystem_ = isSystem;
}
// Used to approximate non-content code when reporting telemetry.
bool isProbablySystemCode() const {
return isSystem_;
}
};
namespace js {

View File

@ -460,7 +460,7 @@ JSContext::setPendingException(const js::Value& v)
inline bool
JSContext::runningWithTrustedPrincipals()
{
return !compartment() || compartment()->principals() == runtime()->trustedPrincipals();
return !realm() || realm()->principals() == runtime()->trustedPrincipals();
}
inline void

View File

@ -256,15 +256,15 @@ ReportError(JSContext* cx, JSErrorReport* reportp, JSErrorCallback callback,
static void
PopulateReportBlame(JSContext* cx, JSErrorReport* report)
{
JSCompartment* compartment = cx->compartment();
if (!compartment)
JS::Realm* realm = cx->realm();
if (!realm)
return;
/*
* Walk stack until we find a frame that is associated with a non-builtin
* rather than a builtin frame and which we're allowed to know about.
*/
NonBuiltinFrameIter iter(cx, compartment->principals());
NonBuiltinFrameIter iter(cx, realm->principals());
if (iter.done())
return;

View File

@ -179,7 +179,7 @@ JSScript::initialEnvironmentShape() const
inline JSPrincipals*
JSScript::principals()
{
return compartment()->principals();
return realm()->principals();
}
inline void

View File

@ -3343,7 +3343,7 @@ js::DescribeScriptedCallerForCompilation(JSContext* cx, MutableHandleScript mayb
return;
}
NonBuiltinFrameIter iter(cx, cx->compartment()->principals());
NonBuiltinFrameIter iter(cx, cx->realm()->principals());
if (iter.done()) {
maybeScript.set(nullptr);

View File

@ -876,8 +876,8 @@ JS_PUBLIC_API(size_t)
JS::SystemRealmCount(JSContext* cx)
{
size_t n = 0;
for (CompartmentsIter comp(cx->runtime(), WithAtoms); !comp.done(); comp.next()) {
if (comp->isSystem())
for (RealmsIter realm(cx->runtime(), WithAtoms); !realm.done(); realm.next()) {
if (realm->isSystem())
++n;
}
return n;
@ -887,8 +887,8 @@ JS_PUBLIC_API(size_t)
JS::UserRealmCount(JSContext* cx)
{
size_t n = 0;
for (CompartmentsIter comp(cx->runtime(), WithAtoms); !comp.done(); comp.next()) {
if (!comp->isSystem())
for (RealmsIter realm(cx->runtime(), WithAtoms); !realm.done(); realm.next()) {
if (!realm->isSystem())
++n;
}
return n;

View File

@ -614,8 +614,8 @@ SavedFrameSubsumedByCaller(JSContext* cx, HandleSavedFrame frame)
if (!subsumes)
return true;
auto currentCompartmentPrincipals = cx->compartment()->principals();
MOZ_ASSERT(!ReconstructedSavedFramePrincipals::is(currentCompartmentPrincipals));
auto currentRealmPrincipals = cx->realm()->principals();
MOZ_ASSERT(!ReconstructedSavedFramePrincipals::is(currentRealmPrincipals));
auto framePrincipals = frame->getPrincipals();
@ -626,7 +626,7 @@ SavedFrameSubsumedByCaller(JSContext* cx, HandleSavedFrame frame)
if (framePrincipals == &ReconstructedSavedFramePrincipals::IsNotSystem)
return true;
return subsumes(currentCompartmentPrincipals, framePrincipals);
return subsumes(currentRealmPrincipals, framePrincipals);
}
// Return the first SavedFrame in the chain that starts with |frame| whose
@ -771,29 +771,29 @@ namespace {
//
// We want callers to pass us the object they were actually passed, not an
// unwrapped form of it. That way Xray access to SavedFrame objects should not
// be affected by AutoMaybeEnterFrameCompartment and the only things that will
// be affected by AutoMaybeEnterFrameRealm and the only things that will
// be affected will be cases in which privileged code works with some C++ object
// that then pokes at an unprivileged StackFrame it has on hand.
class MOZ_STACK_CLASS AutoMaybeEnterFrameCompartment
class MOZ_STACK_CLASS AutoMaybeEnterFrameRealm
{
public:
AutoMaybeEnterFrameCompartment(JSContext* cx,
HandleObject obj
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
AutoMaybeEnterFrameRealm(JSContext* cx,
HandleObject obj
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
MOZ_RELEASE_ASSERT(cx->compartment());
MOZ_RELEASE_ASSERT(cx->realm());
if (obj)
MOZ_RELEASE_ASSERT(obj->compartment());
MOZ_RELEASE_ASSERT(obj->realm());
// Note that obj might be null here, since we're doing this before
// UnwrapSavedFrame.
if (obj && cx->compartment() != obj->compartment())
if (obj && cx->realm() != obj->realm())
{
JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes;
if (subsumes && subsumes(cx->compartment()->principals(),
obj->compartment()->principals()))
if (subsumes && subsumes(cx->realm()->principals(),
obj->realm()->principals()))
{
ar_.emplace(cx, obj);
}
@ -832,7 +832,7 @@ GetSavedFrameSource(JSContext* cx, HandleObject savedFrame, MutableHandleString
MOZ_RELEASE_ASSERT(cx->compartment());
{
AutoMaybeEnterFrameCompartment ac(cx, savedFrame);
AutoMaybeEnterFrameRealm ar(cx, savedFrame);
bool skippedAsync;
js::RootedSavedFrame frame(cx, UnwrapSavedFrame(cx, savedFrame, selfHosted, skippedAsync));
if (!frame) {
@ -855,7 +855,7 @@ GetSavedFrameLine(JSContext* cx, HandleObject savedFrame, uint32_t* linep,
MOZ_RELEASE_ASSERT(cx->compartment());
MOZ_ASSERT(linep);
AutoMaybeEnterFrameCompartment ac(cx, savedFrame);
AutoMaybeEnterFrameRealm ar(cx, savedFrame);
bool skippedAsync;
js::RootedSavedFrame frame(cx, UnwrapSavedFrame(cx, savedFrame, selfHosted, skippedAsync));
if (!frame) {
@ -875,7 +875,7 @@ GetSavedFrameColumn(JSContext* cx, HandleObject savedFrame, uint32_t* columnp,
MOZ_RELEASE_ASSERT(cx->compartment());
MOZ_ASSERT(columnp);
AutoMaybeEnterFrameCompartment ac(cx, savedFrame);
AutoMaybeEnterFrameRealm ar(cx, savedFrame);
bool skippedAsync;
js::RootedSavedFrame frame(cx, UnwrapSavedFrame(cx, savedFrame, selfHosted, skippedAsync));
if (!frame) {
@ -895,7 +895,7 @@ GetSavedFrameFunctionDisplayName(JSContext* cx, HandleObject savedFrame, Mutable
MOZ_RELEASE_ASSERT(cx->compartment());
{
AutoMaybeEnterFrameCompartment ac(cx, savedFrame);
AutoMaybeEnterFrameRealm ar(cx, savedFrame);
bool skippedAsync;
js::RootedSavedFrame frame(cx, UnwrapSavedFrame(cx, savedFrame, selfHosted, skippedAsync));
if (!frame) {
@ -918,7 +918,7 @@ GetSavedFrameAsyncCause(JSContext* cx, HandleObject savedFrame, MutableHandleStr
MOZ_RELEASE_ASSERT(cx->compartment());
{
AutoMaybeEnterFrameCompartment ac(cx, savedFrame);
AutoMaybeEnterFrameRealm ar(cx, savedFrame);
bool skippedAsync;
// This function is always called with self-hosted frames excluded by
// GetValueIfNotCached in dom/bindings/Exceptions.cpp. However, we want
@ -948,7 +948,7 @@ GetSavedFrameAsyncParent(JSContext* cx, HandleObject savedFrame, MutableHandleOb
CHECK_REQUEST(cx);
MOZ_RELEASE_ASSERT(cx->compartment());
AutoMaybeEnterFrameCompartment ac(cx, savedFrame);
AutoMaybeEnterFrameRealm ar(cx, savedFrame);
bool skippedAsync;
js::RootedSavedFrame frame(cx, UnwrapSavedFrame(cx, savedFrame, selfHosted, skippedAsync));
if (!frame) {
@ -981,7 +981,7 @@ GetSavedFrameParent(JSContext* cx, HandleObject savedFrame, MutableHandleObject
CHECK_REQUEST(cx);
MOZ_RELEASE_ASSERT(cx->compartment());
AutoMaybeEnterFrameCompartment ac(cx, savedFrame);
AutoMaybeEnterFrameRealm ar(cx, savedFrame);
bool skippedAsync;
js::RootedSavedFrame frame(cx, UnwrapSavedFrame(cx, savedFrame, selfHosted, skippedAsync));
if (!frame) {
@ -1094,11 +1094,11 @@ BuildStackString(JSContext* cx, HandleObject stack, MutableHandleString stringp,
MOZ_ASSERT(format != js::StackFormat::Default);
// Enter a new block to constrain the scope of possibly entering the stack's
// compartment. This ensures that when we finish the StringBuffer, we are
// back in the cx's original compartment, and fulfill our contract with
// callers to place the output string in the cx's current compartment.
// realm. This ensures that when we finish the StringBuffer, we are back in
// the cx's original compartment, and fulfill our contract with callers to
// place the output string in the cx's current realm.
{
AutoMaybeEnterFrameCompartment ac(cx, stack);
AutoMaybeEnterFrameRealm ar(cx, stack);
bool skippedAsync;
js::RootedSavedFrame frame(cx, UnwrapSavedFrame(cx, stack, SavedFrameSelfHosted::Exclude,
skippedAsync));
@ -1481,7 +1481,7 @@ SavedStacks::insertFrames(JSContext* cx, MutableHandleSavedFrame frame,
RootedAtom displayAtom(cx, iter.maybeFunctionDisplayAtom());
auto principals = iter.compartment()->principals();
auto principals = JS::GetRealmForCompartment(iter.compartment())->principals();
MOZ_ASSERT_IF(framePtr && !iter.isWasm(), iter.pc());
if (!stackChain->emplaceBack(location.source(),

View File

@ -1995,7 +1995,7 @@ intrinsic_AddContentTelemetry(JSContext* cx, unsigned argc, Value* vp)
MOZ_ASSERT(id < JS_TELEMETRY_END);
MOZ_ASSERT(id >= 0);
if (!cx->compartment()->isProbablySystemCode())
if (!cx->realm()->isProbablySystemCode())
cx->runtime()->addTelemetry(id, args[1].toInt32());
args.rval().setUndefined();
@ -2795,6 +2795,8 @@ JSRuntime::createSelfHostingGlobal(JSContext* cx)
if (!compartment)
return nullptr;
JS::Realm* realm = JS::GetRealmForCompartment(compartment);
static const ClassOps shgClassOps = {
nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr,
@ -2807,14 +2809,14 @@ JSRuntime::createSelfHostingGlobal(JSContext* cx)
&shgClassOps
};
AutoRealmUnchecked ar(cx, compartment);
AutoRealmUnchecked ar(cx, realm);
Rooted<GlobalObject*> shg(cx, GlobalObject::createInternal(cx, &shgClass));
if (!shg)
return nullptr;
cx->runtime()->selfHostingGlobal_ = shg;
compartment->isSelfHosting = true;
compartment->setIsSystem(true);
realm->isSelfHosting = true;
realm->setIsSystem(true);
if (!GlobalObject::initSelfHostingBuiltins(cx, shg, intrinsic_functions))
return nullptr;

View File

@ -225,7 +225,7 @@ uint8_t*
InterpreterStack::allocateFrame(JSContext* cx, size_t size)
{
size_t maxFrames;
if (cx->compartment()->principals() == cx->runtime()->trustedPrincipals())
if (cx->realm()->principals() == cx->runtime()->trustedPrincipals())
maxFrames = MAX_FRAMES_TRUSTED;
else
maxFrames = MAX_FRAMES;

View File

@ -673,12 +673,14 @@ FrameIter::settleOnActivation()
Activation* activation = data_.activations_.activation();
// If the caller supplied principals, only show activations which are subsumed (of the same
// origin or of an origin accessible) by these principals.
// If the caller supplied principals, only show activations which are
// subsumed (of the same origin or of an origin accessible) by these
// principals.
if (data_.principals_) {
JSContext* cx = data_.cx_;
if (JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes) {
if (!subsumes(data_.principals_, activation->compartment()->principals())) {
JS::Realm* realm = JS::GetRealmForCompartment(activation->compartment());
if (!subsumes(data_.principals_, realm->principals())) {
++data_.activations_;
continue;
}