chore: cherry-pick 074d472db745 from chromium#50443
Merged
Conversation
jkleinsc
approved these changes
Mar 24, 2026
|
Release Notes Persisted
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[M146][base] Fix UAF in base::OnceCallbackList on re-entrant Notify()
Before this patch,
base::OnceCallbackListwas susceptible to aheap-use-after-free when
Notify()was called re-entrantly.The UAF occurred because
OnceCallbackList::RunCallback()immediatelyspliced executed nodes out of
callbacks_and intonull_callbacks_.If a nested
Notify()executed a node that an outerNotify()loop wasalready holding an iterator to, and that node's subscription was
subsequently destroyed during the re-entrant cycle, the node would be
physically erased from
null_callbacks_. When control returned to theouter loop, it would attempt to evaluate the now-dangling iterator.
This CL fixes the bug by deferring list mutations until the outermost
iteration completes:
RunCallback()no longer splices nodes during iteration.CancelCallback()hook, which is an extension to the pre-existingCancelNullCallback()with increased responsibilities and clearersemantics.
is_iteratingis true,OnceCallbackListresets the node and stashes its iterator inpending_erasures_.CleanUpNullCallbacksPostIteration()phase runs at the endof the outermost
Notify(), which safely splices executed nodesinto
null_callbacks_and physically erases the pending dead nodes.As a side effect, the type-trait hack in
Notify()based onis_instantiation<CallbackType, OnceCallback>can be removed, becausethis information is exposed directly by
OnceCallbackList::CleanUpNullCallbacksPostIteration().The newly-added unit-test
CallbackListTest.OnceCallbackListCancelDuringReentrantNotify reproduces
the scenario and crashed before this patch.
(cherry picked from commit 36acd49636845be2419269acbe9a5137da3d5d96)
Change-Id: I6b1e2bcb97be1bc8d6a15e5ca7511992e00e1772
Fixed: 489381399
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7627506
Commit-Queue: Mikel Astiz mastiz@chromium.org
Reviewed-by: Gabriel Charette gab@chromium.org
Cr-Original-Commit-Position: refs/heads/main@{#1594520}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7653916
Bot-Commit: Rubber Stamper rubber-stamper@appspot.gserviceaccount.com
Cr-Commit-Position: refs/branch-heads/7680@{#2287}
Cr-Branched-From: 76b7d80e5cda23fe6537eed26d68c92e995c7f39-refs/heads/main@{#1582197}
Notes: Backported fix for 489381399.