Skip to content

Commit ca47d9f

Browse files
committed
[nrf fromtree] bluetooth: host: conn: Check if *conn is not NULL
This commit adds a warning and a Kconfig option to `bt_conn_le_create` and `bt_conn_le_create_synced` functions which are meant to warn a user of a potential leakage of an active connection object. This change is implemented due to frequent incorrect use of the connection pointer where a pointer to an existing connection object is overwritten by `bt_conn_le_create` and `bt_conn_le_create_synced` functions which in turns leads to sporadic critical bugs. See zephyrproject-rtos/zephyr#78284 (comment) for more details. The Kconfig option is introduced instead of always returning the error to not affect current implementations. However, it is recommended to keep this option enabled to avoid potential bugs. Signed-off-by: Pavel Vasilyev <[email protected]> (cherry picked from commit 8acb1cc)
1 parent 32bbd4c commit ca47d9f

File tree

5 files changed

+66
-2
lines changed

5 files changed

+66
-2
lines changed

doc/connectivity/bluetooth/api/connection_mgmt.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ longer period of time, since this ensures that the object remains valid
1515
:c:func:`bt_conn_unref` API is to be used when releasing a reference
1616
to a connection.
1717

18+
A common mistake is to forget unreleasing a reference to a connection
19+
object created by functions :c:func:`bt_conn_le_create` and
20+
:c:func:`bt_conn_le_create_synced`. To protect against this, use the
21+
:kconfig:option:`CONFIG_BT_CONN_CHECK_NULL_BEFORE_CREATE` Kconfig option,
22+
which forces these functions return an error if the connection pointer
23+
passed to them is not NULL. This helps to spot such issues and avoid
24+
sporadic bugs caused by not releasing the connection object.
25+
1826
An application may track connections by registering a
1927
:c:struct:`bt_conn_cb` struct using the :c:func:`bt_conn_cb_register`
2028
or :c:macro:`BT_CONN_CB_DEFINE` APIs. This struct lets the application

doc/releases/release-notes-4.0.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ Bluetooth
9898

9999
* The host now disconnects from the peer upon ATT timeout.
100100

101+
* Added a warning to :c:func:`bt_conn_le_create` and :c:func:`bt_conn_le_create_synced` if
102+
the connection pointer passed as an argument is not NULL.
103+
104+
* Added Kconfig option :kconfig:option:`CONFIG_BT_CONN_CHECK_NULL_BEFORE_CREATE` to enforce
105+
:c:func:`bt_conn_le_create` and :c:func:`bt_conn_le_create_synced` return an error if the
106+
connection pointer passed as an argument is not NULL.
107+
101108
* HCI Drivers
102109

103110
Boards & SoC Support

include/zephyr/bluetooth/conn.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,7 +1336,9 @@ struct bt_conn_le_create_param {
13361336
* Allows initiate new LE link to remote peer using its address.
13371337
*
13381338
* The caller gets a new reference to the connection object which must be
1339-
* released with bt_conn_unref() once done using the object.
1339+
* released with bt_conn_unref() once done using the object. If
1340+
* @kconfig{CONFIG_BT_CONN_CHECK_NULL_BEFORE_CREATE} is enabled, this function
1341+
* will return -EINVAL if dereferenced @p conn is not NULL.
13401342
*
13411343
* This uses the General Connection Establishment procedure.
13421344
*
@@ -1375,7 +1377,9 @@ struct bt_conn_le_create_synced_param {
13751377
* with Responses (PAwR) train.
13761378
*
13771379
* The caller gets a new reference to the connection object which must be
1378-
* released with bt_conn_unref() once done using the object.
1380+
* released with bt_conn_unref() once done using the object. If
1381+
* @kconfig{CONFIG_BT_CONN_CHECK_NULL_BEFORE_CREATE} is enabled, this function
1382+
* will return -EINVAL if dereferenced @p conn is not NULL.
13791383
*
13801384
* This uses the Periodic Advertising Connection Procedure.
13811385
*

subsys/bluetooth/host/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,17 @@ config BT_CONN_PARAM_ANY
314314
min and max connection intervals in order to verify whether the
315315
desired parameters have been established in the connection.
316316

317+
config BT_CONN_CHECK_NULL_BEFORE_CREATE
318+
bool "Check if *conn is NULL when creating a connection"
319+
help
320+
Enable this option to ensure that bt_conn_le_create and
321+
bt_conn_le_create_synced return an error if *conn is not initialized
322+
to NULL. This option is recommended to use to catch programming
323+
errors where the application reuses the connection pointer of an
324+
active connection object without dereferencing it. Without
325+
dereferencing, the connection object stays alive which can lead to an
326+
unpredictable behavior.
327+
317328
config BT_USER_PHY_UPDATE
318329
bool "User control of PHY Update Procedure"
319330
depends on BT_PHY_UPDATE

subsys/bluetooth/host/conn.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3718,6 +3718,23 @@ int bt_conn_le_create(const bt_addr_le_t *peer, const struct bt_conn_le_create_p
37183718
struct bt_conn *conn;
37193719
int err;
37203720

3721+
CHECKIF(ret_conn == NULL) {
3722+
return -EINVAL;
3723+
}
3724+
3725+
CHECKIF(*ret_conn != NULL) {
3726+
/* This rule helps application developers prevent leaks of connection references. If
3727+
* a bt_conn variable is not null, it presumably holds a reference and must not be
3728+
* overwritten. To avoid this warning, initialize the variables to null, and set
3729+
* them to null when moving the reference.
3730+
*/
3731+
LOG_WRN("*conn should be unreferenced and initialized to NULL");
3732+
3733+
if (IS_ENABLED(CONFIG_BT_CONN_CHECK_NULL_BEFORE_CREATE)) {
3734+
return -EINVAL;
3735+
}
3736+
}
3737+
37213738
err = conn_le_create_common_checks(peer, conn_param);
37223739
if (err) {
37233740
return err;
@@ -3777,6 +3794,23 @@ int bt_conn_le_create_synced(const struct bt_le_ext_adv *adv,
37773794
struct bt_conn *conn;
37783795
int err;
37793796

3797+
CHECKIF(ret_conn == NULL) {
3798+
return -EINVAL;
3799+
}
3800+
3801+
CHECKIF(*ret_conn != NULL) {
3802+
/* This rule helps application developers prevent leaks of connection references. If
3803+
* a bt_conn variable is not null, it presumably holds a reference and must not be
3804+
* overwritten. To avoid this warning, initialize the variables to null, and set
3805+
* them to null when moving the reference.
3806+
*/
3807+
LOG_WRN("*conn should be unreferenced and initialized to NULL");
3808+
3809+
if (IS_ENABLED(CONFIG_BT_CONN_CHECK_NULL_BEFORE_CREATE)) {
3810+
return -EINVAL;
3811+
}
3812+
}
3813+
37803814
err = conn_le_create_common_checks(synced_param->peer, conn_param);
37813815
if (err) {
37823816
return err;

0 commit comments

Comments
 (0)