Repository navigation
android: Clone replacements into LinearAlloc - #410
Open
pandasauce wants to merge 2 commits into
Open
pandasauce wants to merge 2 commits into
pandasauce wants to merge 2 commits into
Conversation
pandasauce
force-pushed
the
feature/new-garbage-collector
branch
from
October 6, 2026 12:24
6536b5b to
739c46f
Compare
With the new userfaultfd (CMC) collector, ART only updates the declaring_class_ of ArtMethods allocated in its LinearAlloc. The replacement clones lived on the native heap, so they went stale on compaction and crashed DoCall and the GC's own stack walk. When gUseUserfaultfd is set, allocate the clone with Runtime::CreateCalleeSaveMethod() on a runnable thread and copy the original into it. Other collectors keep using Memory.dup().
pandasauce
force-pushed
the
feature/new-garbage-collector
branch
from
October 6, 2026 12:26
739c46f to
b77771a
Compare
Without this, we would leak every time .implementation was reassigned. With this, we only leak the first time a method gets hooked, future reassignments reuse the existing LinearAlloc slot.
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.
Background
Java objects, including class objects, live on the managed heap. Android's GC moves them around to defragment memory. After moving something, it must fix every pointer to it.
ART can fix the class pointer inside an
ArtMethodonly because it knows where those structs are. It allocates them in its own tracked memory area, calledLinearAlloc, and walks that area to update the pointers.Latest ART uses a new moving collector, CMC. It only walks
LinearAllocwhen it moves things.Frida's copy lived in ordinary native memory, so the GC never saw it and never updated its class pointer. After a compaction, the Frida copy's class pointer was stale. The next call into the hooked method, or the GC's own walk of a thread's stack, followed the pointer and read garbage. That produced crashes.
Frida already had a workaround: GC hooks that copy the pointer back from the original afterwards. On my device that fix-up ran too late, or not at all. It runs after the GC finishes, and it has to wait for the script lock.
Change summary
When the device uses CMC, Frida asks ART to allocate the copy's memory. It calls an exported ART function that returns a fresh
ArtMethodslot inLinearAlloc, then copies the original into it. The GC now knows about the copy and fixes its class pointer like any other method. Other collectors still use the old plain copy.Caveats:
LinearAllocdoes not expose an API to do so), but is re-used on each re-assignment of.implementation, so we only pay the price once per methodCreateCalleeSaveMethod) allocating inLinearAlloc, which holds on my device'slibart.sobut isn't guaranteed across all devices/ART versions