5343c336cd97d19868024a11e1e5f3b299d979f8 [chromecast] Fix UAF in BufferedSpdyFramer::OnGoAwayFrameData
Triage note: visitor_->OnGoAway() synchronously destroys the SpdySession and its BufferedSpdyFramer, then old code called goaway_fields_.reset() on freed this. Fix std::move()s goaway_fields_ to a local first. Network-reachable from a malicious HTTP/2 GOAWAY; explicit 'Fix UAF'.
The bug at a glance
Use-after-free in net/spdy’s BufferedSpdyFramer, which runs inside the privileged network service / browser process while parsing attacker-influenced HTTP/2 control frames; a browser-process UAF reachable from any HTTP/2 (or gRPC/Cast) peer is typically rated High.
A malicious or compromised HTTP/2 server (the commit subject flags the Cast receiver path) can send a crafted GOAWAY frame to free the framer object and then have Chrome dereference it, giving an attacker a controlled free-then-use in the process that brokers all network traffic.
Root cause
In BufferedSpdyFramer::OnGoAwayFrameData, once the GOAWAY payload has finished streaming the code calls visitor_->OnGoAway(goaway_fields_->…). That visitor callback synchronously tears down the SpdySession, and because the SpdySession owns the BufferedSpdyFramer, the framer object (and its goaway_fields_ member) is destructed inside the call. The original code then executed goaway_fields_.reset() on the just-freed member, a use-after-free. The invariant violated is that this/goaway_fields_ must not be touched after a visitor callback that can re-enter and destroy the framer. The fix moves goaway_fields_ into a local std::unique_ptr fields before the callback, so ownership (and the GoAwayFields storage) lives on the stack frame; the callback’s arguments are read from the local, and no member access occurs after OnGoAway returns, so the dangling destruction is eliminated.
Key code
net/spdy/buffered_spdy_framer.cc — steal ownership of goaway_fields_ onto the stack before the re-entrant visitor call
std::unique_ptr<GoAwayFields> fields = std::move(goaway_fields_);
visitor_->OnGoAway(fields->last_accepted_stream_id, fields->error_code,
fields->debug_data);
return true;
Patch walkthrough
net/spdy/buffered_spdy_framer.cc— OnGoAwayFrameData previously called visitor_->OnGoAway() reading directly from the goaway_fields_ member, then ran goaway_fields_.reset(). Because visitor_->OnGoAway can synchronously destroy the SpdySession that owns this framer, that trailing member access was a UAF. The patch replaces it with a std::move of goaway_fields_ into a stack local and passes fields->… into OnGoAway, then returns true — the GoAwayFields object is now owned by the stack local and destroyed when the frame unwinds, not by a member touch after the callback.
Background
BufferedSpdyFramer — net/spdy helper that buffers multi-part HTTP/2 control frames (HEADERS, GOAWAY, etc.) and surfaces complete frames to a BufferedSpdyFramer::Visitor, usually the SpdySession.
GOAWAY frame — HTTP/2 connection-shutdown frame carrying last_accepted_stream_id, error_code and optional debug_data; receiving it normally causes Chrome to tear down the SpdySession.
goaway_fields_ — A std::unique_ptr member of BufferedSpdyFramer that accumulates the streamed GOAWAY payload before the visitor is notified.
Re-entrant destruction — visitor_->OnGoAway destroys the SpdySession, which owns the BufferedSpdyFramer, so the callback deletes this and its members mid-method — the classic Chrome callback-frees-the-object UAF shape.
Vulnerability window
- Fix authored — Commit 5343c336cd, dated 2026-09-28, landed to main (CL 8272371).
- Tracking — Internal bug referenced in the change; described as a UAF crash fixed by stealing ownership of goaway_fields_ before the callback.
- Validation — No regression test is included; correctness rests on the ownership move alone.
Proof of concept
The diff contains no regression test or repro, so no trigger code can be grounded in the patch. Conceptually (inferred): a peer HTTP/2 server completes a GOAWAY frame to BufferedSpdyFramer; OnGoAwayFrameData calls visitor_->OnGoAway, the SpdySession is synchronously destroyed (destroying the framer), and the pre-patch goaway_fields_.reset() then touches the freed framer. Reproducing the destroy-on-OnGoAway ordering and any heap grooming is (inferred).
Exploitation
- Reach — Get Chrome to hold an HTTP/2 connection to an attacker-controlled endpoint and send a GOAWAY whose delivery drives OnGoAwayFrameData to completion.
- Free — visitor_->OnGoAway synchronously destructs the SpdySession and its BufferedSpdyFramer, freeing the object whose goaway_fields_ is accessed next.
- Use / escalate — (inferred) Turning the dangling goaway_fields_.reset() into controlled read/write would require reclaiming the freed framer allocation with attacker-shaped data and is not shown by the patch; RCE/sandbox impact beyond the crash is (inferred).
Detection & hunting
For defenders and detection engineers:
- ASAN/heap crash in OnGoAwayFrameData — On ASAN or MTE builds, a heap-use-after-free with BufferedSpdyFramer::OnGoAwayFrameData / SpdySession teardown on the stack is a direct hit; triage network-service crashes with goaway_fields_ in the free/use frames.
- GOAWAY-triggered crashes — Correlate browser/network-service crashes against sessions that received a GOAWAY immediately prior; repeated crashes tied to a specific origin or Cast peer after GOAWAY are suspicious.
- Malformed/edge-case GOAWAY traffic — At a TLS-terminating proxy or Cast gateway, flag peers that emit GOAWAY in unusual sequences or timing designed to force synchronous session teardown.
Audit directions
- net/spdy visitor callbacks — Audit every BufferedSpdyFramer::Visitor dispatch (OnHeaders, OnRstStream, OnSettings, OnDataFrameHeader) for member or this access after the callback, since the visitor can destroy the owning SpdySession.
- Callback-then-member pattern — Grep net/ for ‘visitor_->On…(member_->…); member_.reset();’ or member access following any delegate/visitor invocation that can re-enter and delete the object; prefer moving owned state to a stack local before the call.
- SpdySession ownership graph — Map which framer/parser objects are owned by SpdySession and ensure none are touched after any path that may synchronously destroy the session (GOAWAY, fatal protocol errors, connection close).