tp: extract IncrementalState to fix CustomState UAF (#5593) 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)
Perfetto is an open-source suite of SDKs, daemons and tools which use tracing to help developers understand the behaviour of complex systems and root-cause functional and performance issues on client and embedded systems.
It is a production-grade tool that is the default tracing system for the Android operating system and the Chromium browser.
Perfetto is not a single tool, but a collection of components that work together:
Perfetto was designed to be a versatile and powerful tracing system for a wide range of use cases.
ftrace, allowing you to visualize scheduling, syscalls, interrupts, and custom kernel tracepoints on a timeline.chrome://tracing. Use it to debug and root-cause issues in the browser, V8, and Blink.We‘ve designed our documentation to guide you to the right information as quickly as possible, whether you’re a newcomer to performance analysis or an experienced developer.
New to tracing? If you're unfamiliar with concepts like tracing and profiling, start here:
Ready to dive in? Our “Getting Started” guide is the main entry point for all users. It will help you find the right tutorials and documentation for your specific needs:
Want the full overview? For a comprehensive look at what Perfetto is, why it's useful, and who uses it, see our main documentation page:
For users interested in the Debian distribution of Perfetto, the official source of truth and packaging efforts are maintained at Debian Perfetto Salsa Repository
Have questions? Need help?
We follow Google's Open Source Community Guidelines.