Skip to content

Bluetooth: Controller: Fix missing connection handle invalidate #89481

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

cvinayak
Copy link
Collaborator

@cvinayak cvinayak commented May 5, 2025

Fix missing connection handle invalidate on Controller power up.

The connection context are zero-initialized on startup and calls to ll_connected_get() would incorrectly return a valid connection context pointer for connection handle 0.

@cvinayak cvinayak requested a review from Copilot May 5, 2025 11:00
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes an issue where connection handles were not properly invalidated on Controller power up, preventing an erroneous valid connection context for handle 0. Key changes include:

  • Stopping active tickers related to connection roles before reset.
  • Shifting connection handle invalidation to init_reset().
  • Removing redundant invalidation from the disable() function.

@cvinayak cvinayak force-pushed the github_conn_null_dereference_fix branch from 23bb13d to c0e1856 Compare May 5, 2025 11:08
@cvinayak cvinayak requested a review from Copilot May 5, 2025 11:08
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR addresses an issue where connection handle 0 was not properly invalidated on power up, which caused ll_connected_get() to return an incorrect valid pointer. Key changes include adding a ticker stop routine, explicitly invalidating connection handles in init_reset, and removing duplicate invalidation logic from disable.

Comments suppressed due to low confidence (2)

subsys/bluetooth/controller/ll_sw/ull_conn.c:1672

  • Ensure that ll_conn_get(handle) always returns a valid pointer or add an assertion to prevent potential null dereference if future changes alter connection pool initialization.
for (uint16_t handle = 0U; handle < CONFIG_BT_MAX_CONN; handle++) {

subsys/bluetooth/controller/ll_sw/ull_conn.c:1676

  • [nitpick] With the invalidation now performed in init_reset, please confirm that removing it from disable does not result in inconsistent states when disable is invoked later in the connection lifecycle.
conn->lll.handle = LLL_HANDLE_INVALID;

Tronil
Tronil previously approved these changes May 5, 2025
@cvinayak cvinayak force-pushed the github_conn_null_dereference_fix branch from c0e1856 to a1ba224 Compare May 5, 2025 13:20
@cvinayak
Copy link
Collaborator Author

cvinayak commented May 5, 2025

Updated commit message to refer to cvinayak@fa02dc4

@cvinayak cvinayak requested a review from Thalley May 6, 2025 06:41
@cvinayak cvinayak force-pushed the github_conn_null_dereference_fix branch from a1ba224 to e4b62a3 Compare May 26, 2025 04:38
@cvinayak cvinayak closed this May 26, 2025
@cvinayak cvinayak reopened this May 26, 2025
@cvinayak cvinayak requested review from Thalley, Copilot and Tronil May 26, 2025 08:20
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR ensures connection contexts are properly invalidated on power-up to prevent stale handles (especially handle 0) from appearing valid.

  • Add range checks in ll_conn_get and ll_connected_get to return NULL for out-of-range or uninitialized handles
  • Initialize all connection handles to LLL_HANDLE_INVALID in init_reset
  • Sprinkle LL_ASSERT(conn) after handle lookups to catch invalid contexts early

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c Added LL_ASSERT(conn) to guard against NULL
subsys/bluetooth/controller/ll_sw/ull_iso.c Added LL_ASSERT(conn) in resume ticker start
subsys/bluetooth/controller/ll_sw/ull_conn_iso.c Added LL_ASSERT(conn) in multiple callbacks
subsys/bluetooth/controller/ll_sw/ull_conn.c Added range check in ll_conn_get/ll_connected_get, invalidation loop in init_reset
subsys/bluetooth/controller/ll_sw/ull_central_iso.c Added LL_ASSERT(conn) after ll_conn_get calls
subsys/bluetooth/controller/ll_sw/ull.c Added LL_ASSERT(conn) in RX release and demux
subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c Added LL_ASSERT(conn_lll) guards in LLL prepare and ISR
subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c Added LL_ASSERT(conn_lll) guards in LLL callbacks and ISRs
Comments suppressed due to low confidence (2)

subsys/bluetooth/controller/ll_sw/ull_conn.c:1571

  • The assertion LL_ASSERT(link->next) is redundant here since this branch is only entered when link->next == (void *)tx, which cannot be NULL. Consider removing the assert or adjusting it to capture a more meaningful invariant.
LL_ASSERT(link->next);

subsys/bluetooth/controller/ll_sw/ull_conn.c:1864

  • The code removed resetting conn->lll.handle in disable(), so after disabling a connection the handle field remains valid and ll_connected_get() may return a stale context. Reintroduce invalidation of conn->lll.handle here if disabling should fully tear down the connection state.
conn->lll.link_tx_free = NULL;

Tronil
Tronil previously approved these changes May 26, 2025
conn = ll_conn_get(handle);
if (conn->lll.handle != handle) {
if (!conn || conn->lll.handle != handle) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (!conn || conn->lll.handle != handle) {
if (conn == NULL || conn->lll.handle != handle) {

@@ -804,6 +807,9 @@ struct lll_conn *ull_conn_lll_get(uint16_t handle)
struct ll_conn *conn;

conn = ll_conn_get(handle);
if (!conn) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (!conn) {
if (conn == NULL) {

@@ -155,6 +155,7 @@ static int prepare_cb(struct lll_prepare_param *p)

/* Get reference to ACL context */
conn_lll = ull_conn_lll_get(cis_lll->acl_handle);
LL_ASSERT(conn_lll);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
LL_ASSERT(conn_lll);
LL_ASSERT(conn_lll != NULL);

Applies many places

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this new requirement? Most Bluetooth subsystem code uses !buf style. Shouldn't existing code be updated to be consistent?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a commit and a revert commit as there is code size increase in use of explicit comparison.

The assertion check is correct to have, but the explicit checks seems an overhead due to coding style (both Bluetooth subsystem and few kernel code break this style anyway).

I have come to realization that these invalid checks like LL_ASSERT; and explicit comparisons total ~15 KB of code size on Cortex-M CPUs in the Controller hci_uart builds!

Reference exercise: #90599

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's surprising :o Do you know why changing from e.g. conn_lll) to conn_lll != NULL increase the code size?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently, on investigation, the assert string includes the conditional as string! ... i will put back the MISRA coding style.

cvinayak added 2 commits May 27, 2025 05:49
Fix missing connection handle invalidate on Controller
power up.

The connection context are zero-initialized on startup and
calls to `ll_connected_get()` would incorrectly return a
valid connection context pointer for connection handle 0.

Relates to commit fa02dc4 ("Bluetooth: Controller: Fix
missing reset of connection handle").

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
Add ll_conn_get() return value check for valid connection
context.

Build command:
cmake -GNinja -DBOARD=nrf52833dk/nrf52833
 -DEXTRA_CONF_FILE=overlay-all-bt_ll_sw_split.conf
 -DDTC_OVERLAY_FILE=boards/nrf52833dk_nrf52833_df.overlay
 -DSNIPPET="bt-ll-sw-split" ../../samples/bluetooth/hci_uart
ninja

Before:
Memory region         Used Size  Region Size  %age Used
           FLASH:      283716 B       512 KB     54.11%
             RAM:      109752 B       128 KB     83.73%
        IDT_LIST:          0 GB        32 KB      0.00%

After:
Memory region         Used Size  Region Size  %age Used
           FLASH:      284992 B       512 KB     54.36%
             RAM:      109752 B       128 KB     83.73%
        IDT_LIST:          0 GB        32 KB      0.00%

After (use of `conn != NULL`):
Memory region         Used Size  Region Size  %age Used
           FLASH:      285044 B       512 KB     54.37%
             RAM:      109752 B       128 KB     83.73%
        IDT_LIST:          0 GB        32 KB      0.00%

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
@cvinayak cvinayak force-pushed the github_conn_null_dereference_fix branch from 3617d8a to f275761 Compare May 27, 2025 04:19
Thalley
Thalley previously approved these changes May 27, 2025
Copy link
Collaborator

@Thalley Thalley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will approve for now to get this fix in. The code size and coding guidelines issues can be further investigated outside this PR

@cvinayak
Copy link
Collaborator Author

Will approve for now to get this fix in. The code size and coding guidelines issues can be further investigated outside this PR

On some more investigation, the code size increase is due to the assert string including the conditional (not due to explicit comparison!) . I will go back to using MISRA coding guidelines in this PR. The code size increase is acceptable.

Remove conn variable NULL check before calling
ull_cp_release_tx() to support conditional compilation of
LLCP_TX_CTRL_BUF_QUEUE_ENABLE variant.

Relates to commit 1ff458e ("Bluetooth: controller:
llcp: fixing tx buffer queue handling").

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
@cvinayak cvinayak dismissed stale reviews from Thalley and Tronil via d63e9fa May 27, 2025 07:29
@cvinayak cvinayak force-pushed the github_conn_null_dereference_fix branch from f275761 to d63e9fa Compare May 27, 2025 07:29
Copy link

@cvinayak cvinayak requested review from Tronil and Copilot May 27, 2025 12:39
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR addresses an issue where a connection context for handle 0 was incorrectly considered valid by ensuring proper invalidation of connection handles and adding runtime assertions. Key changes include:

  • Adding LL_ASSERT checks after retrieving connection contexts.
  • Modifying ll_conn_get() and ll_connected_get() to better validate connection handles.
  • Introducing connection handle invalidation during initialization.

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c Added assertion to confirm non-NULL connection after retrieval from ll_conn_get().
subsys/bluetooth/controller/ll_sw/ull_iso.c Added similar LL_ASSERT checks for connection context retrieval.
subsys/bluetooth/controller/ll_sw/ull_conn_iso.c Introduced LL_ASSERT checks to ensure valid connection context before operating on it.
subsys/bluetooth/controller/ll_sw/ull_conn.c Updated ll_conn_get() and ll_connected_get(); moved connection handle invalidation to init_reset.
subsys/bluetooth/controller/ll_sw/ull_central_iso.c Added assertions confirming non-NULL connection contexts in various CIS-related functions.
subsys/bluetooth/controller/ll_sw/ull.c Added LL_ASSERT checks for connection usage in RX memory release and demux functions.
subsys/bluetooth/controller/ll_sw/nordic/lll_peripheral_iso.c Added assertions ensuring valid ACL context retrieval.
subsys/bluetooth/controller/ll_sw/nordic/lll_central_iso.c Added additional LL_ASSERT checks to validate ACL context retrieval.
Comments suppressed due to low confidence (1)

subsys/bluetooth/controller/ll_sw/ull_conn.c:1692

  • The removal of direct connection handle invalidation in the disable() function may lead to cases where a stale connection handle is still referenced; please confirm that moving invalidation to init_reset() covers all necessary scenarios.
conn->lll.handle = LLL_HANDLE_INVALID;

@kartben kartben merged commit ff26592 into zephyrproject-rtos:main May 28, 2025
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants