diff --git a/components/script_bindings/codegen/codegen.py b/components/script_bindings/codegen/codegen.py index bf609cf563b..1013e1a01fa 100644 --- a/components/script_bindings/codegen/codegen.py +++ b/components/script_bindings/codegen/codegen.py @@ -3213,7 +3213,8 @@ create_global_object::( raw.as_ptr() as *const libc::c_void, {TRACE_HOOK_NAME}::, obj.handle_mut(), - origin); + origin, + {"true" if self.descriptor.useSystemCompartment else "false"}); assert!(!obj.is_null()); let root = raw.reflect_with(obj.get()); diff --git a/components/script_bindings/codegen/configuration.py b/components/script_bindings/codegen/configuration.py index e540b0c3101..f7ca3303927 100644 --- a/components/script_bindings/codegen/configuration.py +++ b/components/script_bindings/codegen/configuration.py @@ -252,6 +252,7 @@ class Descriptor(DescriptorProvider): self.outerObjectHook = desc.get('outerObjectHook', 'None') self.proxy = False self.weakReferenceable = desc.get('weakReferenceable', False) + self.useSystemCompartment = desc.get('useSystemCompartment', False) # If we're concrete, we need to crawl our ancestor interfaces and mark # them as having a concrete descendant. diff --git a/components/script_bindings/interface.rs b/components/script_bindings/interface.rs index e185cfe9cfd..bb7e27df910 100644 --- a/components/script_bindings/interface.rs +++ b/components/script_bindings/interface.rs @@ -17,10 +17,10 @@ use js::jsapi::{ HandleObject as RawHandleObject, IsSharableCompartment, IsSystemCompartment, JS_AtomizeAndPinString, JS_GetFunctionObject, JS_GetProperty, JS_IterateCompartments, JS_NewFunction, JS_NewGlobalObject, JS_NewObject, JS_NewStringCopyN, JS_SetReservedSlot, - JS_WrapObject, JSAutoRealm, JSClass, JSClassOps, JSContext, JSFUN_CONSTRUCTOR, JSFunctionSpec, - JSObject, JSPROP_ENUMERATE, JSPROP_PERMANENT, JSPROP_READONLY, JSPROP_RESOLVING, - JSPropertySpec, JSString, JSTracer, ObjectOps, OnNewGlobalHookOption, SymbolCode, - TrueHandleValue, Value, jsid, + JS_SetTrustedPrincipals, JS_WrapObject, JSAutoRealm, JSClass, JSClassOps, JSContext, + JSFUN_CONSTRUCTOR, JSFunctionSpec, JSObject, JSPROP_ENUMERATE, JSPROP_PERMANENT, + JSPROP_READONLY, JSPROP_RESOLVING, JSPropertySpec, JSString, JSTracer, ObjectOps, + OnNewGlobalHookOption, SymbolCode, TrueHandleValue, Value, jsid, }; use js::jsval::{JSVal, NullValue, PrivateValue}; use js::rust::wrappers::{ @@ -142,15 +142,33 @@ pub(crate) unsafe fn create_global_object( trace: TraceHook, mut rval: MutableHandleObject, origin: &MutableOrigin, + use_system_compartment: bool, ) { assert!(rval.is_null()); let mut options = RealmOptions::default(); options.creationOptions_.traceGlobal_ = Some(trace); options.creationOptions_.sharedMemoryAndAtomics_ = false; - select_compartment(cx, &mut options); + if use_system_compartment { + options.creationOptions_.compSpec_ = CompartmentSpecifier::NewCompartmentAndZone; + options.creationOptions_.__bindgen_anon_1.comp_ = std::ptr::null_mut(); + } else { + select_compartment(cx, &mut options); + } + // “System or addon” principals control JIT policy (IsBaselineJitEnabled, IsIonEnabled) and WASM policy + // (IsSimdPrivilegedContext, HasSupport). This is unrelated to the concept of “system” compartments, though WASM + // HasSupport describes checking this flag as “check trusted principals”, which seems to be a mistake. + // Servo currently creates all principals as non-system-or-addon principals. let principal = ServoJSPrincipals::new::(origin); + if use_system_compartment { + // “System” compartments are those that have all “system” realms, which in turn are those that were + // created with the runtime’s global “trusted” principals. This influences the IsSystemCompartment() check + // in select_compartment() below [1], preventing compartment reuse in either direction between this global + // and any globals created with `use_system_compartment` set to false. + // [1] IsSystemCompartment() → Realm::isSystem() → Realm::isSystem_ → principals == trustedPrincipals() + JS_SetTrustedPrincipals(*cx, principal.as_raw()); + } rval.set(JS_NewGlobalObject( *cx,