Skip to content

Commit 8acb1cc

Browse files
PavelVPVdleach02
authored andcommitted
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 #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 <pavel.vasilyev@nordicsemi.no>
1 parent 4ab766c commit 8acb1cc

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
@@ -123,6 +123,13 @@ Bluetooth
123123

124124
* The host now disconnects from the peer upon ATT timeout.
125125

126+
* Added a warning to :c:func:`bt_conn_le_create` and :c:func:`bt_conn_le_create_synced` if
127+
the connection pointer passed as an argument is not NULL.
128+
129+
* Added Kconfig option :kconfig:option:`CONFIG_BT_CONN_CHECK_NULL_BEFORE_CREATE` to enforce
130+
:c:func:`bt_conn_le_create` and :c:func:`bt_conn_le_create_synced` return an error if the
131+
connection pointer passed as an argument is not NULL.
132+
126133
* HCI Drivers
127134

128135
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
@@ -343,6 +343,17 @@ config BT_CONN_PARAM_ANY
343343
min and max connection intervals in order to verify whether the
344344
desired parameters have been established in the connection.
345345

346+
config BT_CONN_CHECK_NULL_BEFORE_CREATE
347+
bool "Check if *conn is NULL when creating a connection"
348+
help
349+
Enable this option to ensure that bt_conn_le_create and
350+
bt_conn_le_create_synced return an error if *conn is not initialized
351+
to NULL. This option is recommended to use to catch programming
352+
errors where the application reuses the connection pointer of an
353+
active connection object without dereferencing it. Without
354+
dereferencing, the connection object stays alive which can lead to an
355+
unpredictable behavior.
356+
346357
config BT_USER_PHY_UPDATE
347358
bool "User control of PHY Update Procedure"
348359
depends on BT_PHY_UPDATE

subsys/bluetooth/host/conn.c

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

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

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

0 commit comments

Comments
 (0)