New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 884897 link

Starred by 1 user

Issue metadata

Status: Fixed
Owner:
Closed: Oct 4
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Mac
Pri: 1
Type: Bug



Sign in to add a comment

caBLE on MacOS sporadically crashes

Project Member Reported by kpaulhamus@chromium.org, Sep 17

Issue description

Exercising caBLE via the phone-as-a-security key flow on MacOS results in crashes, ~1/10 of the time.

martinkr@:

"What all of them have in common is this sequence, somewhere in the stack:
0x00007fff43918e99	(CoreBluetooth + 0x0000fe99 )	-[CBPeripheral handleAttributeEvent:args:attributeSelector:delegateSelector:delegateFlag:]
0x00007fff43918fcc	(CoreBluetooth + 0x0000ffcc )	-[CBPeripheral handleCharacteristicEvent:characteristicSelector:delegateSelector:delegateFlag:]
0x00007fff43914a1e	(CoreBluetooth + 0x0000ba1e )	-[CBPeripheral handleMsg:args:]
0x00007fff4390f4ca	(CoreBluetooth + 0x000064ca )	-[CBCentralManager handleMsg:args:]
0x00007fff4391d8ad	(CoreBluetooth + 0x000148ad )	__30-[CBXpcConnection _handleMsg:]_block_invoke

In one of the variants, on top of that sequence, you can see BluetoothLowEnergyPeripheralDelegate::dealloc crash with a nullptr dereference."
 
Cc: arnarb@chromium.org
Cc: tengs@chromium.org
Cc: ortuno@chromium.org reillyg@chromium.org
For folks with Crash access, the dumps can be found in [1]. Furthermore, the crashes in [2] have -[BluetoothLowEnergyPeripheralDelegate dealloc] on the stack. Judging by the names appearing of the call stack, this seems to happen in response to a message from the Characteristic. My best guess would be this is a message from the notifying fidoStatus characteristic [3], but I'm not sure.

The crash in BluetoothLowEnergyPeripheralDelegate dealloc seems weird too, GetPeripheral() should not be null, as the delegate is destructed before the peripheral in BluetoothLowEnergyDeviceMac [4], maybe there is a double-free going on?

My current working assumption is that first for some reason the Device instance gets destroyed, and then a characteristic notification for the device arrives. This will then lead to a crash, as the corresponding characteristic instance is already destroyed. Would it be possible to run Canary with --enable-logging=stderr and --vmodule="*/fido/*=2,*/bluetooth/*=3" to obtain more logs and see what exactly is happening?

Adding a few BT folks as well, who might have some insight.

[1] http://crash/browse?q=EXISTS+%28SELECT+1+FROM+UNNEST%28CrashedStackTrace.StackFrame%29+WHERE+FunctionName%3D%27-%5BCBPeripheral+handleAttributeEvent%3Aargs%3AattributeSelector%3AdelegateSelector%3AdelegateFlag%3A%5D%27%29+AND+product_name%3D%27Chrome_Mac%27&stbtiq=&reportid=&index=0

[2] http://crash/browse?q=EXISTS+%28SELECT+1+FROM+UNNEST%28CrashedStackTrace.StackFrame%29+WHERE+FunctionName%3D%27-%5BCBPeripheral+handleAttributeEvent%3Aargs%3AattributeSelector%3AdelegateSelector%3AdelegateFlag%3A%5D%27%29+AND+product_name%3D%27Chrome_Mac%27+AND+EXISTS+%28SELECT+1+FROM+UNNEST%28CrashedStackTrace.StackFrame%29+WHERE+FunctionName%3D%27-%5BBluetoothLowEnergyPeripheralDelegate+dealloc%5D%27%29&stbtiq=&reportid=0fc3106bd8465272&index=0#0

[3] https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html#ble-fido-service

[4] https://codesearch.chromium.org/chromium/src/device/bluetooth/bluetooth_low_energy_device_mac.h?l=147-152&rcl=04ce8e41ff6a9c5404f852666488f7e5be6037ec
Cc: jlebel@chromium.org
In case we get lucky and this is indeed a double-free of natively allocated objects, we should try reproducing with an ASAN-instrumented build.
Or using Malloc Scribble, Malloc Guard Edges, Guard Malloc or Zombie Objects should help too.
Cc: sacamoto@chromium.org
Here's my best understanding as to what is going on: It is a use-after-free of the BluetoothLowEnergyDeviceMac, and happens in the following way:

On construction of the BluetoothLowEnergyDeviceMac, it constructs a BluetoothLowEnergyPeripheralDelegate and sets it as the delegate of the passed in CBPeripheral [1]. This increases the delegate's ref-count, as now both the device as well as the CoreBluetooth implementation have a reference to the delegate.

However, the BluetoothLowEnergyPeripheralDelegate implicitly assumes that it is outlived by the BluetoothLowEnergyDeviceMac, as it only keeps a raw pointer to it [2]. Now, once the GetAssertion request completes, it releases the kept reference to the BluetoothAdapter, which causes all BluetoothLowEnergyDeviceMac to be destroyed.

Soon after, the BluetoothLowEnergyPeripheralDelegate gets destroyed as well, and it accesses the stored raw pointer to the device to clear out the peripheral's delegate [3]. However, the device is already destroyed at this point, resulting in a use-after-free. 

Here is the corresponding ASAN crash: http://gpaste/6469705820798976

I have a fix in https://crrev.com/c/1233737 that stops accessing the device in the delegate's destructor and moves the clearing out of the peripheral's delegate to the destructor of the device.


[1] https://codesearch.chromium.org/chromium/src/device/bluetooth/bluetooth_low_energy_device_mac.mm?l=49&rcl=8f9ac80abbd502800b8a77101482a1285f7fc9a8

[2] https://codesearch.chromium.org/chromium/src/device/bluetooth/bluetooth_low_energy_peripheral_delegate.mm?l=63&rcl=f7ef1c942101a6560f1d5487a3688d13eaa15be4

[3] https://codesearch.chromium.org/chromium/src/device/bluetooth/bluetooth_low_energy_peripheral_delegate.mm?l=60,79&rcl=f7ef1c942101a6560f1d5487a3688d13eaa15be4
As far as I know BluetoothLowEnergyPeripheralDelegate is only retained by BluetoothLowEnergyDeviceMac. It is not retained by CBPeripheral.

But anyway, I agree with the conclusion. Since BluetoothLowEnergyDeviceMac sets the delegate of CBPeripheral, it should be responsible for removing the delegate. After BluetoothLowEnergyDeviceMac being deallocated, both CBPeripheral and BluetoothLowEnergyPeripheralBridge will be deallocated since they should not be retained anymore, but we don't know in which order they will be destroyed.

I guess I made that bug. And that bug must exist in other places like:
With BluetoothAdapterMac and BluetoothLowEnergyCentralManagerDelegate:
https://cs.chromium.org/chromium/src/device/bluetooth/bluetooth_adapter_mac.mm?l=136
https://cs.chromium.org/chromium/src/device/bluetooth/bluetooth_low_energy_central_manager_delegate.mm?l=72

With BluetoothAdapterMac and BluetoothLowEnergyPeripheralManagerDelegate:
https://cs.chromium.org/chromium/src/device/bluetooth/bluetooth_adapter_mac.mm?l=148
https://cs.chromium.org/chromium/src/device/bluetooth/bluetooth_low_energy_peripheral_manager_delegate.mm?l=59
Labels: Type-Bug
Owner: jdoerrie@chromium.org
Status: Assigned
Project Member

Comment 11 by bugdroid1@chromium.org, Sep 20

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/493245617aeeb1bd5ecdcbbbf2eb62282379b48c

commit 493245617aeeb1bd5ecdcbbbf2eb62282379b48c
Author: Jan Wilken Dörrie <jdoerrie@chromium.org>
Date: Thu Sep 20 09:56:35 2018

[Bluetooth][Mac] Fix Use After Free in macOS BLE Stack

This change fixes bugs in the macOS BLE stack where delegates
outlived the object they were observing and caused use-after-frees.

Bug:  884897 
Change-Id: Ib38164851fb6ab57cc56f9684f8b43161d59e13a
Reviewed-on: https://chromium-review.googlesource.com/1233737
Reviewed-by: Jérôme Lebel <jlebel@chromium.org>
Reviewed-by: Giovanni Ortuño Urquidi <ortuno@chromium.org>
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#592742}
[modify] https://crrev.com/493245617aeeb1bd5ecdcbbbf2eb62282379b48c/device/bluetooth/bluetooth_adapter_mac.mm
[modify] https://crrev.com/493245617aeeb1bd5ecdcbbbf2eb62282379b48c/device/bluetooth/bluetooth_low_energy_central_manager_delegate.mm
[modify] https://crrev.com/493245617aeeb1bd5ecdcbbbf2eb62282379b48c/device/bluetooth/bluetooth_low_energy_device_mac.mm
[modify] https://crrev.com/493245617aeeb1bd5ecdcbbbf2eb62282379b48c/device/bluetooth/bluetooth_low_energy_peripheral_delegate.mm
[modify] https://crrev.com/493245617aeeb1bd5ecdcbbbf2eb62282379b48c/device/bluetooth/bluetooth_low_energy_peripheral_manager_delegate.mm

Given this fixes a pretty bad crash, but is a really small change overall, do you think we can request merge ASAP so this can be included in the earlier Beta release possible?
Cc: -sacamoto@chromium.org sacomoto@chromium.org
Labels: Merge-Request-70
Re c#12: Yep, I agree. Requesting merge of r592742 into M70 (branch 3538).
Project Member

Comment 15 by sheriffbot@chromium.org, Sep 21

Labels: -Merge-Request-70 Merge-Review-70 Hotlist-Merge-Review
This bug requires manual review: M70 has already been promoted to the beta branch, so this requires manual review
Please contact the milestone owner if you have questions.
Owners: benmason@(Android), kariahda@(iOS), geohsu@(ChromeOS), abdulsyed@(Desktop)

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot
Labels: -Merge-Review-70 Merge-Approved-70
Project Member

Comment 17 by bugdroid1@chromium.org, Sep 21

Labels: -merge-approved-70 merge-merged-3538
The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/016ba634e092fce054e1a723b67fe429c6693517

commit 016ba634e092fce054e1a723b67fe429c6693517
Author: Jan Wilken Dörrie <jdoerrie@chromium.org>
Date: Fri Sep 21 23:04:56 2018

[Bluetooth][Mac] Fix Use After Free in macOS BLE Stack

This change fixes bugs in the macOS BLE stack where delegates
outlived the object they were observing and caused use-after-frees.

Bug:  884897 
Change-Id: Ib38164851fb6ab57cc56f9684f8b43161d59e13a
Reviewed-on: https://chromium-review.googlesource.com/1233737
Reviewed-by: Jérôme Lebel <jlebel@chromium.org>
Reviewed-by: Giovanni Ortuño Urquidi <ortuno@chromium.org>
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#592742}(cherry picked from commit 493245617aeeb1bd5ecdcbbbf2eb62282379b48c)
Reviewed-on: https://chromium-review.googlesource.com/1239475
Reviewed-by: Jan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/branch-heads/3538@{#575}
Cr-Branched-From: 79f7c91a2b2a2932cd447fa6f865cb6662fa8fa6-refs/heads/master@{#587811}
[modify] https://crrev.com/016ba634e092fce054e1a723b67fe429c6693517/device/bluetooth/bluetooth_adapter_mac.mm
[modify] https://crrev.com/016ba634e092fce054e1a723b67fe429c6693517/device/bluetooth/bluetooth_low_energy_central_manager_delegate.mm
[modify] https://crrev.com/016ba634e092fce054e1a723b67fe429c6693517/device/bluetooth/bluetooth_low_energy_device_mac.mm
[modify] https://crrev.com/016ba634e092fce054e1a723b67fe429c6693517/device/bluetooth/bluetooth_low_energy_peripheral_delegate.mm
[modify] https://crrev.com/016ba634e092fce054e1a723b67fe429c6693517/device/bluetooth/bluetooth_low_energy_peripheral_manager_delegate.mm

Labels: Merge-Merged-70-3538
The following revision refers to this bug: 
https://chromium.googlesource.com/chromium/src.git/+/016ba634e092fce054e1a723b67fe429c6693517

Commit: 016ba634e092fce054e1a723b67fe429c6693517
Author: jdoerrie@chromium.org
Commiter: jdoerrie@chromium.org
Date: 2018-09-21 23:04:56 +0000 UTC

[Bluetooth][Mac] Fix Use After Free in macOS BLE Stack

This change fixes bugs in the macOS BLE stack where delegates
outlived the object they were observing and caused use-after-frees.

Bug:  884897 
Change-Id: Ib38164851fb6ab57cc56f9684f8b43161d59e13a
Reviewed-on: https://chromium-review.googlesource.com/1233737
Reviewed-by: Jérôme Lebel <jlebel@chromium.org>
Reviewed-by: Giovanni Ortuño Urquidi <ortuno@chromium.org>
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#592742}(cherry picked from commit 493245617aeeb1bd5ecdcbbbf2eb62282379b48c)
Reviewed-on: https://chromium-review.googlesource.com/1239475
Reviewed-by: Jan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/branch-heads/3538@{#575}
Cr-Branched-From: 79f7c91a2b2a2932cd447fa6f865cb6662fa8fa6-refs/heads/master@{#587811}
Status: Fixed (was: Assigned)

Sign in to add a comment