Skip to content

tp: IncrementalState fixes#5751

Merged
LalitMaganti merged 2 commits into
canaryfrom
dev/reveman/gpu-counter-group-fix-canary
May 6, 2026
Merged

tp: IncrementalState fixes#5751
LalitMaganti merged 2 commits into
canaryfrom
dev/reveman/gpu-counter-group-fix-canary

Conversation

@dreveman
Copy link
Copy Markdown
Collaborator

@dreveman dreveman commented May 6, 2026

tp: scope gpu_counter custom-groups cache to per-sequence state (#5742)
tp: extract IncrementalState to fix CustomState UAF (#5593)

LalitMaganti and others added 2 commits May 6, 2026 05:53
Fixes the use-after-free flagged in
`PacketSequenceStateGeneration::CustomState`.

## The bug

Previously, each `CustomState` held a raw `generation_` back-pointer
that was re-pointed every time a new generation was created via
`OnNewTracePacketDefaults` (the `set_generation(this)` loop in the
multi-arg ctor). The `TraceSorter` can hold a `RefPtr` to an older
Generation `G1` while a newer `G2` — to which `G1`'s shared CustomState
had been re-pointed — is dropped after `SEQ_INCREMENTAL_STATE_CLEARED`.
`G1` stays alive (and so does the CustomState), but its `generation_`
then dangles to freed memory; any subsequent lookup through the
CustomState dereferences the freed `G2`.

## The fix

Refactor the generation/CustomState relationship so that lifetime is
correct **by construction**:

- New `IncrementalState : RefCounted`. Owns the
per-incremental-state-interval data: `interned_data_`, the array of
`CustomState`s (now `unique_ptr` rather than `RefPtr`), and the
persistent thread descriptor. A new `IncrementalState` is constructed
only on `SEQ_INCREMENTAL_STATE_CLEARED`.

- `PacketSequenceStateGeneration` becomes a thin
per-`trace_packet_defaults` snapshot: holds `RefPtr<IncrementalState>`
(shared with sibling generations within the same interval), the defaults
blob, and the validity flag. All interned-data / custom-state /
thread-descriptor accessors are forwarders to the `IncrementalState`.

- `CustomState` is no longer `RefCounted` (it's owned uniquely by its
`IncrementalState`). Its back-pointer is `IncrementalState*` and is set
exactly once at lazy-allocation time inside
`IncrementalState::GetCustomState<T>`. Because the `IncrementalState`
owns the `CustomState`, the pointer is stable for the entire life of the
CustomState — UAF impossible.

- `OnNewTracePacketDefaults` no longer copies the `InternedFieldMap` or
re-points CustomStates; it constructs a new Generation that shares the
same `RefPtr<IncrementalState>`. This removes a per-defaults-change copy
that could be O(map-size) in the hot path.

- `OnPacketLoss` walks the IncrementalState's CustomState array and
clears any slot whose `ClearOnPacketLoss()` opted in (TES today), then
returns a new Generation referencing the same `IncrementalState` with
the validity bit cleared.

---

**Stack:**
- #5588 — tp: stop mutating PacketSequenceStateGeneration on packet loss
- #5590 — tp: split TrackEventSequenceState into descriptor + delta
state
- **#5593 — tp: extract IncrementalState to fix CustomState UAF** (this
PR)
gpu_custom_groups_inserted_ in GpuEventParser was a global
FlatHashMap<uint64_t, bool> keyed solely by counter_descriptor_iid, used
to dedupe GpuCounterBlock insertions for the interned descriptor path.
Interned ids are scoped to a packet sequence's incremental-state
interval, not global, so two producers that legitimately share an iid on
different packet sequences collide: whichever arrives first flips the
cache, and the second producer's InsertCustomCounterGroups call is
silently short-circuited. If the first producer's descriptor has no
counter_groups, the second producer's blocks never reach
gpu_counter_group_table and the UI renders those counters flat instead
of grouped.

Move the cache into a new GpuCounterSequenceState : CustomState on
PacketSequenceStateGeneration, alongside the interned-data table the
descriptor was looked up from. Cache key stays plain
counter_descriptor_iid; correctness comes from CustomState being
intrinsically per-sequence per-incremental-state-interval, matching
where the iids are valid. Same pattern as AndroidKernelWakelockState.
@dreveman dreveman requested a review from a team as a code owner May 6, 2026 13:05
@LalitMaganti LalitMaganti merged commit 83989c2 into canary May 6, 2026
2 checks passed
@LalitMaganti LalitMaganti deleted the dev/reveman/gpu-counter-group-fix-canary branch May 6, 2026 13:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants