Chrome · Bluetooth
CVE-2026-14032
UAF in Bluetooth
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifdevice/bluetooth/bluetooth_socket_mac.mm |
modified |
Files Changed
device/bluetooth/bluetooth_socket_mac.mm
Patch
From 375096a7dd434f3fa2a5cff6a8c71c3f3827da83 Mon Sep 17 00:00:00 2001
From: Alvin Ji <alvinji@chromium.org>
Date: Fri, 22 May 2026 20:15:45 -0700
Subject: [PATCH] bluetooth: Fix potential browser-process UAF in socket listeners
Due to an Apple framework bug (FB13705522), IOBluetooth holds an
unsafe_unretained pointer and may dispatch late callbacks to freed
listeners after unregistration.
This CL fixes the UAF by clearing back-pointers and posting a keep-alive
block to the main queue, ensuring the listener safely outlives any
pending OS notifications.
Bug: 495783474
Change-Id: I79497e722159320158bb411fcb15f99066d7ca0e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7833747
Reviewed-by: Matt Reynolds <mattreynolds@chromium.org>
Commit-Queue: Alvin Ji <alvinji@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1635359}
---
diff --git a/device/bluetooth/bluetooth_socket_mac.mm b/device/bluetooth/bluetooth_socket_mac.mm
index 60b5df97..2348f81a 100644
--- a/device/bluetooth/bluetooth_socket_mac.mm
+++ b/device/bluetooth/bluetooth_socket_mac.mm
@@ -122,6 +122,7 @@
channelID:(BluetoothRFCOMMChannelID)channelID;
- (void)rfcommChannelOpened:(IOBluetoothUserNotification*)notification
channel:(IOBluetoothRFCOMMChannel*)rfcommChannel;
+- (void)stopListening;
@end
@@ -150,8 +151,26 @@
[_rfcommNewChannelNotification unregister];
}
+- (void)stopListening {
+ [_rfcommNewChannelNotification unregister];
+ _socket = nullptr;
+
+ // Keep self alive for a brief period to allow any already-enqueued
+ // notifications on the main run loop to fire safely (and become no-ops
+ // since _socket is now null) rather than hitting a deallocated object.
+ // See FB13705522.
+ __strong auto strongSelf = self;
+ dispatch_async(dispatch_get_main_queue(), ^{
+ (void)strongSelf;
+ });
+}
+
- (void)rfcommChannelOpened:(IOBluetoothUserNotification*)notification
channel:(IOBluetoothRFCOMMChannel*)rfcommChannel {
+ if (!_socket) {
+ return;
+ }
+
if (notification != _rfcommNewChannelNotification) {
// This case is reachable if there are pre-existing RFCOMM channels open at
// the time that the listener is created. In that case, each existing
@@ -184,6 +203,7 @@
psm:(BluetoothL2CAPPSM)psm;
- (void)l2capChannelOpened:(IOBluetoothUserNotification*)notification
channel:(IOBluetoothL2CAPChannel*)l2capChannel;
+- (void)stopListening;
@end
@@ -212,8 +232,26 @@
[_l2capNewChannelNotification unregister];
}
+- (void)stopListening {
+ [_l2capNewChannelNotification unregister];
+ _socket = nullptr;
+
+ // Keep self alive for a brief period to allow any already-enqueued
+ // notifications on the main run loop to fire safely (and become no-ops
+ // since _socket is now null) rather than hitting a deallocated object.
+ // See FB13705522.
+ __strong auto strongSelf = self;
+ dispatch_async(dispatch_get_main_queue(), ^{
+ (void)strongSelf;
+ });
+}
+
- (void)l2capChannelOpened:(IOBluetoothUserNotification*)notification
channel:(IOBluetoothL2CAPChannel*)l2capChannel {
+ if (!_socket) {
+ return;
+ }
+
if (notification != _l2capNewChannelNotification) {
// This case is reachable if there are pre-existing L2CAP channels open at
// the time that the listener is created. In that case, each existing
@@ -1001,7 +1039,9 @@
[service_record_ removeServiceRecord];
service_record_ = nil;
+ [rfcomm_connection_listener_ stopListening];
rfcomm_connection_listener_ = nil;
+ [l2cap_connection_listener_ stopListening];
l2cap_connection_listener_ = nil;
// Destroying the listener above prevents the callback delegate from being
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.
References
On This Page