High chrome UAF 🔧 Commit mapped

Overview

High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactImproper input validation in Core
DescriptionImproper input validation in Core
ComponentCore
Sub-componentAndroid
Bug ClassUAF
Tracker568937139
Fix commit01d973c14e9c (chromium/src) +14/-6
CISA KEVNot listed
CreditedGoogle
Disclosed2026-10-27

Background

`OnSelectionEvent` / `UpdateTouchSelectionController`
Methods that react to selection changes and update the touch-selection controller; both can call out synchronously (including JNI into Java).
`ResetGestureDetection`
Cancels gesture detection; it synchronously acks touch-cancel and GestureScrollEnd, which can drive a synchronous WebContents/view teardown.
`destroy_pending()`
A flag indicating the view is mid-teardown; the patched code checks it to bail out before touching this.
`input::ScopedInputDispatchPin`
RAII guard that pins the view (defers its destruction) for the duration of a dispatch, so the object stays alive while methods remain on the stack.
`base::WeakPtr`
The pre-patch guard; it reports whether the object was destroyed but does not prevent destruction, so code that already dereferenced this before the check can still UAF.

Root Cause Analysis

Despite the advisory’s “Improper input validation” label, the diff substantiates a use-after-free of the browser-process RenderWidgetHostViewAndroid. OnSelectionEvent(SELECTION_HANDLES_SHOWN) calls ResetGestureDetection(), whose synchronous touch-cancel / GestureScrollEnd acks can run arbitrary WebContents/view teardown (including synchronous JNI callouts to Java) while OnSelectionEvent, and the UpdateTouchSelectionController it calls, are still executing on the stack. The object they are running on can thus be freed underneath them, and any subsequent member access (e.g. selection_popup_controller_->OnSelectionEvent(...), OnUpdateScopedSelectionHandles()) touches freed memory.

The pre-patch mitigation in UpdateTouchSelectionController captured a base::WeakPtr<RenderWidgetHostViewAndroid> weak_this and checked if (!weak_this) return; afterward — but a WeakPtr check only detects destruction after the fact; it cannot keep the object alive while the method continues to run, and OnSelectionEvent had no such guard at all around ResetGestureDetection(). The patch replaces the weak-pointer scheme with input::ScopedInputDispatchPin pin(this), which actually pins the view against destruction for the scope, and adds explicit destroy_pending() bailouts: at the top of OnSelectionEvent (if (destroy_pending() || !selection_popup_controller_) return;), immediately after ResetGestureDetection(), at the top of UpdateTouchSelectionController, and after UpdateClientSelectionBounds(...). Together these ensure the object survives the reentrant callouts and the code stops touching it once teardown has been requested.

Key insight
A selection/gesture handler called synchronously into code that could destroy its own view, yet guarded only with a WeakPtr that detects—rather than prevents—destruction; the object was freed while the handler was still on the stack.

Attack Path

  1. Enter a selection/gesture state On Android, a web page induces a touch selection so OnSelectionEvent(SELECTION_HANDLES_SHOWN) fires with an active down event (inferred reachability from the diff’s control flow).
  2. Trigger `ResetGestureDetection` With gesture_provider_->GetCurrentDownEvent() set, OnSelectionEvent calls ResetGestureDetection().
  3. Synchronous teardown The resulting touch-cancel / GestureScrollEnd ack (or a JNI callout to Java) synchronously tears down the WebContents/view, freeing the RenderWidgetHostViewAndroid.
  4. Return onto freed `this` Control returns into the still-executing OnSelectionEvent/UpdateTouchSelectionController, which dereference freed member state (selection_popup_controller_, touch_selection_controller_client_manager_).
  5. UAF primitive Reading/calling through freed browser-process memory; with heap grooming this is an exploitable use-after-free in an unsandboxed process (reclaim/control inferred, not shown).

Impact Assessment

The defect is in the browser process on Android, which is unsandboxed, so it is a high-value target. Triggering requires only a web page that drives touch selection plus the specific gesture state, i.e. no elevated privilege (UI interaction is implied). The proven primitive is a use-after-free dereference of the view and its controllers during reentrant teardown; the pin + destroy_pending() checks confirm the lifetime hazard was real. Escalation beyond a controlled crash to code execution is (inferred). Note the advisory class (“Improper input validation”) does not match the code: the diff is a lifetime/reentrancy fix (UAF), not input validation.

Changed Functions

FunctionChangeNotes
if
content/browser/renderer_host/render_widget_host_view_android.cc
modified

Files Changed

  • content/browser/renderer_host/render_widget_host_view_android.cc

Audit Directions

  • Reentrant selection/gesture paths
    Audit other RenderWidgetHostViewAndroid methods that call ResetGestureDetection, ack touch/gesture events, or make JNI callouts while continuing to touch members afterward.
  • WeakPtr-as-lifetime-guard misuse
    Grep for GetWeakPtr() + if (!weak_this) patterns across content/browser/renderer_host; those detect but do not prevent destruction and should likely become pin/destroy_pending() guards.
  • `ScopedInputDispatchPin` coverage
    Verify every input-dispatch entry point that can synchronously destroy its view is wrapped in a pin.
  • Synchronous JNI callouts
    Review Android view code where Java callbacks can run arbitrary teardown during a native method still holding this.
From 01d973c14e9c202c02adda1ffdb4a3eda53273bd Mon Sep 17 00:00:00 2001
From: Kartar Singh <kartarsingh@google.com>
Date: Mon, 19 Oct 2026 12:18:45 -0700
Subject: [PATCH] [Android] Harden OnSelectionEvent against synchronous teardown

Pin RenderWidgetHostViewAndroid with ScopedInputDispatchPin and guard
with destroy_pending() in OnSelectionEvent() and
UpdateTouchSelectionController(). When
OnSelectionEvent(SELECTION_HANDLES_SHOWN) calls ResetGestureDetection(),
synchronous touch-cancel and GestureScrollEnd acks can trigger
synchronous WebContents and view teardown while OnSelectionEvent() and
UpdateTouchSelectionController() are still on the stack.

Bug: 568937139
Change-Id: I915fe95166a9a34bea2ecfcf00616d98bbe255c1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8608092
Reviewed-by: Jonathan Ross <jonross@chromium.org>
Commit-Queue: Jonathan Ross <jonross@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1722211}
---
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 0fdf74b..f2099fe 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -976,9 +976,7 @@
   if (!gesture_listener_manager_)
     return;
 
-  base::WeakPtr<RenderWidgetHostViewAndroid> weak_this =
-      weak_ptr_factory_.GetWeakPtr();
-
+  input::ScopedInputDispatchPin pin(this);
   UpdateTouchSelectionController(
       metadata.selection, metadata.page_scale_factor,
       metadata.browser_controls_metadata.top_controls_height,
@@ -987,7 +985,7 @@
 
   // Abort if the view was destroyed during UpdateTouchSelectionController
   // (e.g. via synchronous JNI callout to Java).
-  if (!weak_this) {
+  if (destroy_pending()) {
     return;
   }
 
@@ -2258,8 +2256,10 @@
 
 void RenderWidgetHostViewAndroid::OnSelectionEvent(
     ui::SelectionEventType event) {
-  if (!selection_popup_controller_)
+  if (destroy_pending() || !selection_popup_controller_) {
     return;
+  }
+  input::ScopedInputDispatchPin pin(this);
   CHECK(touch_selection_controller_, base::NotFatalUntil::M152);
   // If a selection drag has started, it has taken over the active touch
   // sequence. Immediately cancel gesture detection and any downstream touch
@@ -2280,6 +2280,9 @@
     }
     if (gesture_provider_->GetCurrentDownEvent()) {
       ResetGestureDetection();
+      if (destroy_pending() || !selection_popup_controller_) {
+        return;
+      }
     }
   }
   selection_popup_controller_->OnSelectionEvent(
@@ -2383,12 +2386,17 @@
     float top_controls_height,
     float top_controls_shown_ratio,
     const gfx::SizeF& scrollable_viewport_size_dip) {
-  if (!touch_selection_controller_)
+  if (destroy_pending() || !touch_selection_controller_) {
     return;
+  }
+  input::ScopedInputDispatchPin pin(this);
 
   CHECK(touch_selection_controller_client_manager_, base::NotFatalUntil::M152);
   touch_selection_controller_client_manager_->UpdateClientSelectionBounds(
       selection.start, selection.end, this, nullptr);
+  if (destroy_pending()) {
+    return;
+  }
   OnUpdateScopedSelectionHandles();
 
   // Set parameters for adaptive handle orientation.
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.