Type confusion in [@ js::ProxyGetProperty] due to GVN eliding MGuardIsProxy across JSObject::swap
Categories
(Core :: JavaScript Engine: JIT, defect)
Tracking
()
People
(Reporter: bugmon, Unassigned)
Details
(5 keywords)
Attachments
(2 files)
Bug Title: Type confusion in [@ js::ProxyGetProperty] due to GVN eliding MGuardIsProxy across JSObject::swap
Severity: sec-high
Root Cause: Ten MIR instructions had their alias_set changed from AliasSet::Load(AliasSet::ObjectFields) to AliasSet::None() in MIROps.yaml (GuardIsProxy, GuardIsNotDOMProxy, GuardIsNotProxy, GuardIsNativeObject, GuardHasProxyHandler, LoadScriptedProxyHandler, IsConstructor) and MIR.h (MHasClass, MGuardToClass, MIsCallable). With AliasSet::None, these instructions never have a dependency() set, causing GVN to treat congruent instances as mergeable even when separated by effectful calls that can mutate object class.
Exploit Chain:
- Create a FakeDOMObject and transplant it to another compartment, making it a CCW (proxy)
- Warm up
f(o)which does twoo.propaccesses separated by a call tocb(). The GenericProxy IC emitsMGuardIsProxy → MGuardIsNotDOMProxy → MProxyGetfor each access - During Ion compilation, GVN sees two congruent MGuardIsProxy instructions with nullptr dependency → merges them, eliminating the second guard chain. The second MProxyGet now uses the first guard's result
- On the trigger run,
cb()callstp.transplant(globalThis)which swaps the object back to a native FakeDOMObject via JSObject::swap. This does NOT invalidate Ion code because the object has no ObjectFuse - The second MProxyGet executes ProxyGetProperty on a NativeObject. It reads offset 16 (NativeObject::elements_) as if it were ProxyObject::handler, obtaining a pointer to emptyElementsHeader
handler->hasSecurityPolicy()reads 9 bytes past emptyElementsHeader → ASAN global-buffer-overflow
Memory Layout Confusion:
- ProxyObject offset 16 =
const BaseProxyHandler* handler - NativeObject offset 16 =
js::HeapSlot* elements_
The with ({}) in cb() prevents Ion inlining, ensuring cb() compiles to a simple MCall in f's block so GVN can merge the guards across it.
Fix: Restore alias_set: custom with AliasSet::Load(AliasSet::ObjectFields) for all ten modified MIR instructions so that AliasAnalysis correctly tracks dependencies on effectful operations that can change object class.
Flags: --fuzzing-safe --fast-warmup --no-threads
| Reporter | ||
Comment 1•7 months ago
|
||
| Reporter | ||
Comment 2•7 months ago
|
||
Updated•7 months ago
|
Updated•7 months ago
|
| Reporter | ||
Comment 5•7 months ago
|
||
No valid actions for resolution (DUPLICATE).
Removing bugmon keyword as no further action possible. Please review the bug and re-add the keyword for further analysis.
Updated•2 months ago
|
Description
•