diff options
author | Shu-yu Guo <syg@chromium.org> | 2022-05-03 13:26:32 -0700 |
---|---|---|
committer | Michael Brüning <michael.bruning@qt.io> | 2022-07-25 14:22:46 +0000 |
commit | aab054ee7160f3eca2e0c33fe7d617660e945fba (patch) | |
tree | 6d3ba1531b552a86116961d87b60e25bf41d62ee | |
parent | 95bda789ea62fe9ef2aeff10ab0aa4b81ed8e718 (diff) | |
download | qtwebengine-chromium-aab054ee7160f3eca2e0c33fe7d617660e945fba.tar.gz |
[Backport] CVE-2022-2158: Type Confusion in V8
Cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/v8/v8/+/3676863:
Set unregister_token to undefined when unregistering
(cherry picked from commit dd3289d7945dac855d1287cf4ea248883e908d54)
Bug: chromium:1321078
No-Try: true
No-Presubmit: true
No-Tree-Checks: true
Change-Id: I426327ffc3d7eebdb562c01a87039a93dfb79a88
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#80349}
Reviewed-by: Dominik Inführ <dinfuehr@chromium.org>
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
Cr-Commit-Position: refs/branch-heads/9.6@{#68}
Cr-Branched-From: 0b7bda016178bf438f09b3c93da572ae3663a1f7-refs/heads/9.6.180@{#1}
Cr-Branched-From: 41a5a247d9430b953e38631e88d17790306f7a4c-refs/heads/main@{#77244}
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
-rw-r--r-- | chromium/v8/src/heap/mark-compact.cc | 5 | ||||
-rw-r--r-- | chromium/v8/src/objects/js-weak-refs-inl.h | 21 | ||||
-rw-r--r-- | chromium/v8/src/objects/js-weak-refs.h | 8 | ||||
-rw-r--r-- | chromium/v8/src/objects/objects.cc | 2 |
4 files changed, 22 insertions, 14 deletions
diff --git a/chromium/v8/src/heap/mark-compact.cc b/chromium/v8/src/heap/mark-compact.cc index 0fffb4ea458..a284c11fb62 100644 --- a/chromium/v8/src/heap/mark-compact.cc +++ b/chromium/v8/src/heap/mark-compact.cc @@ -2747,14 +2747,11 @@ void MarkCompactCollector::ClearJSWeakRefs() { // unregister_token field set to undefined when processing the first // WeakCell. Like above, we're modifying pointers during GC, so record the // slots. - HeapObject undefined = ReadOnlyRoots(isolate()).undefined_value(); JSFinalizationRegistry finalization_registry = JSFinalizationRegistry::cast(weak_cell.finalization_registry()); finalization_registry.RemoveUnregisterToken( JSReceiver::cast(unregister_token), isolate(), - [undefined](WeakCell matched_cell) { - matched_cell.set_unregister_token(undefined); - }, + JSFinalizationRegistry::kKeepMatchedCellsInRegistry, gc_notify_updated_slot); } else { // The unregister_token is alive. diff --git a/chromium/v8/src/objects/js-weak-refs-inl.h b/chromium/v8/src/objects/js-weak-refs-inl.h index 13ac175cf6e..0e39b00d135 100644 --- a/chromium/v8/src/objects/js-weak-refs-inl.h +++ b/chromium/v8/src/objects/js-weak-refs-inl.h @@ -71,16 +71,14 @@ bool JSFinalizationRegistry::Unregister( // key. Each WeakCell will be in the "active_cells" or "cleared_cells" list of // its FinalizationRegistry; remove it from there. return finalization_registry->RemoveUnregisterToken( - *unregister_token, isolate, - [isolate](WeakCell matched_cell) { - matched_cell.RemoveFromFinalizationRegistryCells(isolate); - }, + *unregister_token, isolate, kRemoveMatchedCellsFromRegistry, [](HeapObject, ObjectSlot, Object) {}); } -template <typename MatchCallback, typename GCNotifyUpdatedSlotCallback> +template <typename GCNotifyUpdatedSlotCallback> bool JSFinalizationRegistry::RemoveUnregisterToken( - JSReceiver unregister_token, Isolate* isolate, MatchCallback match_callback, + JSReceiver unregister_token, Isolate* isolate, + RemoveUnregisterTokenMode removal_mode, GCNotifyUpdatedSlotCallback gc_notify_updated_slot) { // This method is called from both FinalizationRegistry#unregister and for // removing weakly-held dead unregister tokens. The latter is during GC so @@ -118,7 +116,16 @@ bool JSFinalizationRegistry::RemoveUnregisterToken( value = weak_cell.key_list_next(); if (weak_cell.unregister_token() == unregister_token) { // weak_cell has the same unregister token; remove it from the key list. - match_callback(weak_cell); + switch (removal_mode) { + case kRemoveMatchedCellsFromRegistry: + weak_cell.RemoveFromFinalizationRegistryCells(isolate); + break; + case kKeepMatchedCellsInRegistry: + // Do nothing. + break; + } + // Clear unregister token-related fields. + weak_cell.set_unregister_token(undefined); weak_cell.set_key_list_prev(undefined); weak_cell.set_key_list_next(undefined); was_present = true; diff --git a/chromium/v8/src/objects/js-weak-refs.h b/chromium/v8/src/objects/js-weak-refs.h index 250186e7bef..88361ad1c05 100644 --- a/chromium/v8/src/objects/js-weak-refs.h +++ b/chromium/v8/src/objects/js-weak-refs.h @@ -53,10 +53,14 @@ class JSFinalizationRegistry : public JSObject { // it modifies slots in key_map and WeakCells and the normal write barrier is // disabled during GC, we need to tell the GC about the modified slots via the // gc_notify_updated_slot function. - template <typename MatchCallback, typename GCNotifyUpdatedSlotCallback> + enum RemoveUnregisterTokenMode { + kRemoveMatchedCellsFromRegistry, + kKeepMatchedCellsInRegistry + }; + template <typename GCNotifyUpdatedSlotCallback> inline bool RemoveUnregisterToken( JSReceiver unregister_token, Isolate* isolate, - MatchCallback match_callback, + RemoveUnregisterTokenMode removal_mode, GCNotifyUpdatedSlotCallback gc_notify_updated_slot); // Returns true if the cleared_cells list is non-empty. diff --git a/chromium/v8/src/objects/objects.cc b/chromium/v8/src/objects/objects.cc index 99e9ccad058..2bbd2337b18 100644 --- a/chromium/v8/src/objects/objects.cc +++ b/chromium/v8/src/objects/objects.cc @@ -6876,7 +6876,7 @@ void JSFinalizationRegistry::RemoveCellFromUnregisterTokenMap( } // weak_cell is now removed from the unregister token map, so clear its - // unregister token-related fields for heap verification. + // unregister token-related fields. weak_cell.set_unregister_token(undefined); weak_cell.set_key_list_prev(undefined); weak_cell.set_key_list_next(undefined); |