← Chrome — 2026-W36

693bdacc0e27188b423c57fd987d7ce8d018f8aa  Add null check to prevent UAF during shutdown

severity low class UAF CVSS 5.9 signal score 5.3 content/browser/ AI review CONFIRMED
Structural signals: msg_strong (+3.0), area:content/browser/ (+1.0), surgical (+1.3)

The bug at a glance

A use-after-free reachable re-entrantly during RenderWidgetHostViewAura teardown: as rwhva_ is destroyed, selection_controller_ is freed, but the unwind re-enters TouchSelectionControllerClientAura::InvalidateClient, which called GetTouchSelectionController()->HideAndDisallowShowingAutomatically() on the freed/absent controller. It is a browser-process UAF, but it occurs only during shutdown of the view, is not obviously attacker-timed or heap-groomable from a web page, and the fix is a defensive null check — so impact is primarily a crash with limited exploitability rather than reliable control.

During RenderWidgetHostViewAura destruction, the touch-selection controller is torn down, yet a re-entrant path (child-frame touch-selection client destructor -> InvalidateClient) calls back into the now-freed selection controller.

Root cause

RenderWidgetHostViewAura::~RenderWidgetHostViewAura frees selection_controller_. Its destruction chain reaches ~TouchSelectionControllerClientAura -> ~TouchSelectionControllerClientChildFrame -> TouchSelectionControllerClientAura::InvalidateClient. InvalidateClient, when client == active_client_, called GetTouchSelectionController()->HideAndDisallowShowingAutomatically(). At that point the controller has already been freed/cleared, so the dereference is a use-after-free (or null deref). The fix wraps the call in ‘if (GetTouchSelectionController())’ so it is skipped when the controller is gone, while still resetting active_client_/active_menu_client_.

Key code

Null-guarding the touch-selection controller before use during re-entrant teardown.

   if (client == active_client_) {
-    GetTouchSelectionController()->HideAndDisallowShowingAutomatically();
+    if (GetTouchSelectionController()) {
+      GetTouchSelectionController()->HideAndDisallowShowingAutomatically();
+    }
     active_client_ = &internal_client_;
     active_menu_client_ = this;
   }

Patch walkthrough

  • content/browser/renderer_host/input/touch_selection_controller_client_aura.cc — In InvalidateClient(), guards the HideAndDisallowShowingAutomatically() call with an explicit GetTouchSelectionController() null check so that when the controller has already been freed during RenderWidgetHostViewAura destruction the freed-object call is avoided; active_client_ and active_menu_client_ are still reset. The CHECK(client != &internal_client_, NotFatalUntil::M152) above is unchanged.

Background

RenderWidgetHostViewAura (rwhva_) — The Aura (desktop) view for a render widget in the browser process; owns the touch selection controller and clients.

TouchSelectionController — Manages the on-screen text-selection handles/quick menu; HideAndDisallowShowingAutomatically() hides handles. GetTouchSelectionController() returns the (possibly already-destroyed) controller instance.

Re-entrant teardown — Destructor chains that call virtual/client callbacks can re-enter sibling objects after a dependency has been freed, producing use-after-free during shutdown.

NotFatalUntil::M152 — A CHECK scheduled to become fatal in M152; indicates the invariant (client != internal_client_) is being hardened in the same area.

Vulnerability window

  1. Latent bug — InvalidateClient unconditionally dereferenced GetTouchSelectionController(), unsafe when reached during controller/view destruction. (inferred)
  2. Discovery — Tracked as Bug 542565481; a crash stack (HideHandles <- HideAndDisallowShowingAutomatically <- InvalidateClient <- ~ClientChildFrame <- ~ClientAura <- ~RenderWidgetHostViewAura) showed the freed-object call.
  3. Fix — 2026-09-02: null check added around the controller call (this commit).

Proof of concept

Conceptual only. The crash arises during RenderWidgetHostViewAura shutdown with an active touch-selection client in a child frame; reproducing requires destroying a view while touch selection is active (e.g. navigating/closing a frame that owns an active text selection). The diff shows no deterministic trigger and the UAF is a teardown-order race, so no working exploit is provided.

Exploitation

  1. Setup — Page establishes an active touch text selection in an out-of-process/child frame so a TouchSelectionControllerClientChildFrame is the active client. (inferred)
  2. Trigger — The RenderWidgetHostViewAura is destroyed (frame/tab teardown), whose destructor frees selection_controller_ and re-enters InvalidateClient. (inferred)
  3. Use-after-free — InvalidateClient dereferences the already-freed controller via HideAndDisallowShowingAutomatically(); exploitation would require winning the teardown race and grooming the freed allocation, which is difficult. (inferred)

Detection & hunting

For defenders and detection engineers:

  • Crash stack through InvalidateClient during ~RenderWidgetHostViewAura — Watch for ASAN heap-use-after-free or null-deref with the HideHandles/HideAndDisallowShowingAutomatically/InvalidateClient/~TouchSelectionControllerClient* frames noted in the commit message.
  • Shutdown crashes with active touch selection — Correlate crashes to sessions where touch text selection was active in a child frame at view teardown.

Audit directions

  • TouchSelectionControllerClientAura / ChildFrame — Audit all GetTouchSelectionController() dereferences for teardown-time nullability; verify destructor ordering between RenderWidgetHostViewAura, selection_controller_, and client objects.
  • Re-entrant destructor callbacks — Search for client/observer callbacks invoked from destructors that touch sibling objects which may already be freed; add liveness/null checks.

Before / after

Loading diff…