UAF when WeakRef target is Unlinked by CC
Categories
(Core :: JavaScript: GC, defect, P1)
Tracking
()
People
(Reporter: sfink, Assigned: jonco)
References
(Blocks 1 open bug)
Details
(6 keywords, Whiteboard: [bugmon:bisected,confirmed][adv-main150.0.1+r][adv-esr115.35.1+r][adv-esr140.10.1+r])
Attachments
(2 files, 5 external files, 1 obsolete file)
Cloned from bug 2025953, where Clauditor found a way to have a WeakRef to an object that is unlinked as part of a cycle, and the WeakRef allows posthumously reaching that object and things it references.
| Reporter | ||
Comment 1•7 months ago
|
||
bug 2025953 comment 13 from mccr8:
I don't remember how WeakRef integration into the CC works. There are some tests for it, so I'm not sure why this case doesn't work when the other ones do. I assume there's some place we tell the CC about these weak references? I vaguely recall it being hacked into the WeakMap API for that, but if we make a special one for WeakRefs then the CC could track which JS objects are WeakRefs and then drop the referents during CollectWhite (eg the sweeping phase).
bug 2025953 comment 15 from mccr8:
Is there something like we only clear WeakRefs when we return to the event loop and therefore this test case that synchronously runs a CC is mildly bogus? How does that interact with nested event loops? I guess the inner event loop will also trigger a clear?
bug 2025953 comment 16 from jonco:
(In reply to Andrew McCreight [:mccr8] from comment #13)
How does this work in the GC? I assume during sweeping you clear out the referent somehow?
Yes, FinalizationObservers::traceWeakWeakRefEdges checks the list of weak ref targets per zone and clears the referent for any that are dying: https://searchfox.org/firefox-main/source/js/src/gc/FinalizationObservers.cpp#534
I don't remember how WeakRef integration into the CC works. There are some tests for it, so I'm not sure why this case doesn't work when the other ones do. I assume there's some place we tell the CC about these weak references?
I'm not sure there's anything beyond preserving wrappers that are direct targets of WeakRefs. We have WeakMapTracer but that only traces weak maps. We originally used to use weak maps in the weak ref implementation which might have covered this.
We can add an API to check if an object is the target of a weak ref. Or we could add an API to iterate all WeakRef targets. What would work best?
Maybe we should split the weak map part off into a separate bug.
Not relevant to the weak ref issue but I'm confused as to what cycle the CC sees in the test case here. It seems to me it should be AuthenticatorAttestationResponse -> ArrayBuffer -> reponse wrapper -> reponse, but it's implied that PublicKeyCredential is part of it as it is failing to clear the response pointer when it's unlinked.
| Reporter | ||
Comment 2•7 months ago
|
||
| Reporter | ||
Updated•7 months ago
|
| Reporter | ||
Comment 3•7 months ago
|
||
I believe what is happening is that in the reproduction case, the WeakRef target is a plain ArrayBuffer, the attestationObject from:
[SecureContext, Pref="security.webauth.webauthn",
Exposed=Window]
interface AuthenticatorAttestationResponse : AuthenticatorResponse {
[SameObject, Throws] readonly attribute ArrayBuffer attestationObject;
sequence<DOMString> getTransports();
[Throws] ArrayBuffer getAuthenticatorData();
[Throws] ArrayBuffer? getPublicKey();
[Throws] COSEAlgorithmIdentifier getPublicKeyAlgorithm();
};
The way this normally works is that bug 1642974 made it so that when retrieving a WeakRef target, unlinked DOM objects are detected and return undefined. In this case, the target object is a plain ArrayBuffer object, so the relevant code is not able to see that it is part of an unlinked cycle.
| Reporter | ||
Comment 4•7 months ago
|
||
Note that this is exactly the situation mccr8 brought up in bug 1642974 comment 2.
Updated•7 months ago
|
Comment 5•7 months ago
|
||
There's also bug 2028061, which jonco filed. Maybe it could get duped to here?
(In reply to Steve Fink [:sfink] [:s:] from comment #4)
Note that this is exactly the situation mccr8 brought up in bug 1642974 comment 2.
What a bold visionary! Thanks for digging up the history here, Steve, I'd totally forgotten any of it.
How are these weak ref edges presented to the cycle collector? Maybe it just doesn't see them at all?
Kind of feels like there's going to have be some elaborate special case integration in the cycle collector, like during CollectWhite it iterates over all grey weak referents, checks if it thinks they are garbage, and clear the target if so.
Comment 7•7 months ago
|
||
I think this would mostly manifest as weird null deref crashes in DOM nodes, but I don't remember seeing this in great volume. (We had a similar problem with weak references XPCWrappedJS which did show up fairly often at least in our automated tests.)
| Comment hidden (duplicate) |
| Assignee | ||
Comment 9•7 months ago
|
||
This fixes the problem by clearing the targets of WeakRefs when those tagets
are found to be part of a gray cycle by the cycle collector. This is the same
thing that happens for nsWeakReferences which should be cleared when their
targets are unlinked.
This patch does add a lookup for each gray JS thing found to be part of the
cycle. This might do a hash table lookup but there are a couple of checks that
happen first that can short circuit that. Do you think this will add
unreasonable overhead?
This doesn't add any new tests but I confirmed that the new code is exercised
by existing tests.
Updated•7 months ago
|
Updated•7 months ago
|
Updated•7 months ago
|
| Assignee | ||
Comment 10•7 months ago
|
||
This fixes the problem by clearing the targets of WeakRefs when those tagets
are found to be part of a gray cycle by the cycle collector. This is the same
thing that happens for nsWeakReferences which should be cleared when their
targets are unlinked.
This version looks up all WeakRef targets in the cycle collector table to check
whether they are white. If so their corresponding WeakRefs are cleared. This
requires a hash table lookup for every weak ref rather than for every white GC
thing found by the cycle collector.
Updated•7 months ago
|
| Assignee | ||
Comment 11•7 months ago
|
||
| Assignee | ||
Comment 12•7 months ago
|
||
Comment on attachment 9568219 [details]
(secure)
Security Approval Request
- How easily could an exploit be constructed based on the patch?: Very difficult.
- Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: No
- Which branches (beta, release, and/or ESR) are affected by this flaw, and do the release status flags reflect this affected/unaffected state correctly?: All supportd branches
- If not all supported branches, which bug introduced the flaw?: None
- Do you have backports for the affected branches?: No
- If not, how different, hard to create, and risky will they be?: Should be simple.
- How likely is this patch to cause regressions; how much testing does it need?: This is a straightforward fix and is unlikely to cause regressions.
- Is the patch ready to land after security approval is given?: Yes
- Is Android affected?: Yes
Updated•7 months ago
|
Comment 13•6 months ago
|
||
Comment 14•6 months ago
|
||
Unable to reproduce bug 2028231 using build mozilla-central 20260331210827-1369941f425d. Without a baseline, bugmon is unable to analyze this bug.
Removing bugmon keyword as no further action possible. Please review the bug and re-add the keyword for further analysis.
Comment 15•6 months ago
|
||
https://hg-edge.mozilla.org/mozilla-central/rev/ff7d7cd6ef98
Please nominate this for Beta, ESR140, and ESR115 uplift.
| Assignee | ||
Comment 16•6 months ago
|
||
Updated•6 months ago
|
Comment 17•6 months ago
|
||
firefox-esr140 Uplift Approval Request
- User impact if declined/Reason for urgency: Possible crash / security vulnerability
- Code covered by automated testing?: yes
- Fix verified in Nightly?: yes
- Needs manual QE testing?: no
- Steps to reproduce for manual QE testing:
- Risk associated with taking this patch: low
- Explanation of risk level: This is a straightfoward fix to clear the targets of WeakRefs when those targets are found to be part of a cycle that the CC will unlink. This has been on central for three days without issues.
- String changes made/needed?: None
- Is Android affected?: yes
| Assignee | ||
Comment 18•6 months ago
|
||
Updated•6 months ago
|
Comment 19•6 months ago
|
||
firefox-esr115 Uplift Approval Request
- User impact if declined/Reason for urgency: Possible crash / security vulnerability.
- Code covered by automated testing?: yes
- Fix verified in Nightly?: yes
- Needs manual QE testing?: no
- Steps to reproduce for manual QE testing:
- Risk associated with taking this patch: low
- Explanation of risk level: This is a straightfoward fix to clear the targets of WeakRefs when those targets are found to be part of a cycle that the CC will unlink. This has been on central for three days without issues.
- String changes made/needed?: None
- Is Android affected?: yes
Comment 20•6 months ago
•
|
||
:jonco still needs a beta one if we want this in todays ESR build
Updated•6 months ago
|
Updated•6 months ago
|
Updated•6 months ago
|
Comment 21•6 months ago
|
||
| uplift | ||
Comment 22•6 months ago
|
||
:Jonco this actually had some bustage on esr115
failure log
It appears the issue might occur on both esr patches.
Updated•6 months ago
|
Updated•6 months ago
|
Comment 23•6 months ago
|
||
| backout uplift | ||
Updated•6 months ago
|
| Assignee | ||
Comment 24•6 months ago
|
||
This fixes the problem by clearing the targets of WeakRefs when those tagets
are found to be part of a gray cycle by the cycle collector. This is the same
thing that happens for nsWeakReferences which should be cleared when their
targets are unlinked.
This patch looks up all WeakRef targets in the cycle collector table to check
whether they are white. If so their corresponding WeakRefs are cleared. This
requires a hash table lookup for every weak ref.
Original Revision: https://phabricator.services.mozilla.com/D293099
Updated•6 months ago
|
Comment 25•6 months ago
|
||
firefox-beta Uplift Approval Request
- User impact if declined/Reason for urgency: Possible crash / security vulnerability.
- Code covered by automated testing?: yes
- Fix verified in Nightly?: yes
- Needs manual QE testing?: no
- Steps to reproduce for manual QE testing:
- Risk associated with taking this patch: low
- Explanation of risk level: This is a straightforward fix to clear the targets of WeakRefs when those targets are found to be part of a cycle that the CC will unlink. This has been on central for four days without issues.
- String changes made/needed?: None
- Is Android affected?: yes
| Assignee | ||
Updated•6 months ago
|
Updated•6 months ago
|
Updated•6 months ago
|
Comment 26•6 months ago
|
||
The patch landed in nightly and beta is affected.
:jonco, is this bug important enough to require an uplift?
- If yes, please nominate the patch for beta approval.
- See https://wiki.mozilla.org/Release_Management/Requesting_an_Uplift for documentation on how to request an uplift.
- If no, please set
status-firefox150towontfix.
For more information, please visit BugBot documentation.
| Assignee | ||
Updated•6 months ago
|
Updated•6 months ago
|
Updated•6 months ago
|
Updated•6 months ago
|
Comment 27•6 months ago
|
||
| uplift | ||
Updated•6 months ago
|
Updated•6 months ago
|
Comment 28•6 months ago
|
||
| uplift | ||
Updated•6 months ago
|
Updated•6 months ago
|
Comment 29•6 months ago
|
||
| uplift | ||
Updated•6 months ago
|
Comment 30•6 months ago
|
||
| 140.10.1 uplift | ||
Updated•6 months ago
|
Comment 31•6 months ago
|
||
| 115.35.1 uplift | ||
Updated•6 months ago
|
Updated•6 months ago
|
Updated•2 months ago
|
Updated•2 months ago
|
Comment 32•2 months ago
|
||
Comment 33•2 months ago
|
||
| bugherder | ||
Description
•