zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.83k stars 6.6k forks source link

Bluetooth: Host: No space to store CCC when GATT client loses bond and CCC Lazy Loading is enabled #61033

Closed alstrzebonski closed 1 year ago

alstrzebonski commented 1 year ago

Describe the bug When previously bonded GATT client reconnects and CONFIG_BT_SETTINGS_CCC_LAZY_LOADING is enabled, CCC configuration is loaded from Settings. If GATT client had lost bond and CONFIG_BT_GATT_AUTO_SEC_REQ is disabled, GATT client can stay connected without reestablishing security. However, when this GATT client tries to write CCC on previously used Attribute it can't do that and following log message appears: LOG_WRN("No space to store CCC cfg");. It happens because the find_ccc_cfg function in subsys/bluetooth/host/gatt.c returns error. That's because the existing CCC for the GATT client can't be overwritten as the security is not reestablished (as expected) and also there is no space to store new CCC configuration, because cfg array length in struct _bt_gatt_ccc is set to CONFIG_BT_MAX_CONN which is often equal to 1. When CONFIG_BT_SETTINGS_CCC_LAZY_LOADING is disabled, the cfg array length is set to CONFIG_BT_MAX_PAIRED + CONFIG_BT_MAX_CONN and the issue doesn't replicate, because there is enough space to store new CCC configuration.

To Reproduce Steps to reproduce the behavior:

  1. Build and flash zephyr/samples/bluetooth/peripheral sample with BT_GATT_AUTO_SEC_REQ disabled.
  2. Pair with the sample from your Bluetooth central (e.g. phone). The phone automatically writes Service Changed CCC. You can also manually write some others CCC (e.g. Battery Service) using e.g. nRF Connect app.
  3. Unpair your phone.
  4. Reconnect your phone without pairing (you can do that via nRF Connect app)
  5. Write Service Changed CCC or some other CCC that you have written in step 2.
  6. See that the CCC write fails with warning message: No space to store CCC cfg.

You can verify that it doesn't reproduce if CONFIG_BT_SETTINGS_CCC_LAZY_LOADING is disabled.

Expected behavior The CCC write should succeed regardless of CONFIG_BT_SETTINGS_CCC_LAZY_LOADING being enabled or no. The phone doesn't want to overwrite the existing CCC. It wants to write new one as it has lost bond.

Impact Google Fast Pair Service protocol (https://developers.google.com/nearby/fast-pair/specifications/introduction) requires using GATT before bonding. Because of that, if a Phone loses bond, it is unable to bond again using Fast Pair, because it is unable to write CCC when CONFIG_BT_SETTINGS_CCC_LAZY_LOADING is enabled.

Environment (please complete the following information):

github-actions[bot] commented 1 year ago

Hi @alstrzebonski! We appreciate you submitting your first issue for our open-source project. 🌟

Even though I'm a bot, I can assure you that the whole community is genuinely grateful for your time and effort. 🤖💙

alwa-nordic commented 1 year ago

I agree that the same result should be expected regardless of CONFIG_BT_SETTINGS_CCC_LAZY_LOADING.

jori-nordic commented 1 year ago

Might be fixed by https://github.com/zephyrproject-rtos/zephyr/pull/62985

alstrzebonski commented 1 year ago

Might be fixed by #62985

Yes, it fixes this issue, because now CCC cfg can be overwritten by peer that doesn't reestablish security which was not allowed earlier.