Skip to content

nimble/host: Evict stale resolving list entry before adding - #2282

Open
sanastasiou wants to merge 1 commit into
apache:masterfrom
sanastasiou:host-pvcy-evict-stale-rl-entry
Open

nimble/host: Evict stale resolving list entry before adding#2282
sanastasiou wants to merge 1 commit into
apache:masterfrom
sanastasiou:host-pvcy-evict-stale-rl-entry

Conversation

@sanastasiou

Copy link
Copy Markdown

Problem

Some controllers reject LE Add Device To Resolving List with Invalid HCI Command Parameters (0x12) when an entry for that peer identity is already present.

ble_hs_pvcy_add_entry() does not handle this. The error propagates to ble_store_write_peer_sec(), which discards it:

/* There is not much to do here if it fails */

The controller is therefore left resolving the old IRK, and the host has no way to notice — the resolving list cannot be read back.

Impact

Reachable whenever a peer re-pairs over an existing bond.

Peers that rotate their IRK on unpair — Android does — become permanently unresolvable afterwards. The controller silently drops their CONNECT_IND because it still holds the previous IRK. There is no error anywhere: the peer simply stops being able to reconnect. The only recovery is a reset that rebuilds the resolving list from the bond store.

Peers with a stable IRK are unaffected, which is why this typically presents as "Android cannot reconnect after re-pairing, iOS is fine".

Fix

Remove any existing entry for the identity before the add. Removing an absent entry is harmless, so no prior lookup is needed — and since the resolving list is not readable, a lookup is not generally possible anyway.

Note the call is to ble_hs_pvcy_remove_entry_hci() rather than ble_hs_pvcy_remove_entry(). The latter wraps the command in its own ble_gap_preempt() / ble_gap_preempt_done() pair, and ble_gap_preempt_done() is not depth counted — using it here would end the preemption established a few lines above, before the add is issued. That preemption is required by Vol 2, Part E, 7.8.38.

Testing

Observed and fixed on an ESP32-C3 (NimBLE-Arduino, BLE_HOST_BASED_PRIVACY=0, so the resolving list lives in the controller).

Before: every re-pair over an existing bond logged rc=530 (BLE_HS_HCI_ERR(0x12)) from the add path, after which the Android peer could no longer reconnect until reboot.

After: the add succeeds, and repeated OS-forget + re-pair cycles reconnect normally. Verified across both an Android peer (rotating IRK) and an iOS peer (stable IRK) to confirm no regression on the previously-working path.

I do not have a multi-controller test bed, so I can only confirm the 0x12 behaviour on the ESP32-C3. The change should be a no-op on controllers that already tolerate a duplicate add.

Some controllers reject LE Add Device To Resolving List with Invalid HCI
Command Parameters (0x12) when an entry for that peer identity already
exists. ble_hs_pvcy_add_entry() does not handle this: the error is returned
to ble_store_write_peer_sec(), which discards it ("There is not much to do
here if it fails"). The controller is then left resolving the OLD IRK.

This is reachable whenever a peer re-pairs over an existing bond. Peers that
rotate their IRK on unpair -- Android does -- become permanently
unresolvable afterwards: the controller silently drops their CONNECT_IND
because it still holds the previous IRK, and the host never learns why. The
only recovery is a reset that rebuilds the resolving list from the bond
store. Peers with a stable IRK are unaffected, which is why this tends to
show up as "Android cannot reconnect after re-pairing, iOS is fine".

Remove any existing entry for the identity before the add. Removing an
absent entry is harmless, so it needs no prior lookup -- and the resolving
list cannot be read back, so a lookup is not possible in the general case
anyway.

Note this calls ble_hs_pvcy_remove_entry_hci() rather than
ble_hs_pvcy_remove_entry(). The latter wraps the command in its own
ble_gap_preempt()/ble_gap_preempt_done() pair, and ble_gap_preempt_done() is
not depth counted, so using it here would end the preemption established
above before the add is issued.

Observed on an ESP32-C3 (NimBLE-Arduino, host based privacy disabled) with
rc=530 == BLE_HS_HCI_ERR(0x12) logged from the add path on every re-pair,
and fixed by this change on the same hardware.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants