Skip to content

Commit fd0492a

Browse files
PavelVPVrlubos
authored andcommitted
[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 7718e6e commit fd0492a

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
@@ -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
@@ -3729,6 +3729,23 @@ int bt_conn_le_create(const bt_addr_le_t *peer, const struct bt_conn_le_create_p
37293729
struct bt_conn *conn;
37303730
int err;
37313731

3732+
CHECKIF(ret_conn == NULL) {
3733+
return -EINVAL;
3734+
}
3735+
3736+
CHECKIF(*ret_conn != NULL) {
3737+
/* This rule helps application developers prevent leaks of connection references. If
3738+
* a bt_conn variable is not null, it presumably holds a reference and must not be
3739+
* overwritten. To avoid this warning, initialize the variables to null, and set
3740+
* them to null when moving the reference.
3741+
*/
3742+
LOG_WRN("*conn should be unreferenced and initialized to NULL");
3743+
3744+
if (IS_ENABLED(CONFIG_BT_CONN_CHECK_NULL_BEFORE_CREATE)) {
3745+
return -EINVAL;
3746+
}
3747+
}
3748+
37323749
err = conn_le_create_common_checks(peer, conn_param);
37333750
if (err) {
37343751
return err;
@@ -3788,6 +3805,23 @@ int bt_conn_le_create_synced(const struct bt_le_ext_adv *adv,
37883805
struct bt_conn *conn;
37893806
int err;
37903807

3808+
CHECKIF(ret_conn == NULL) {
3809+
return -EINVAL;
3810+
}
3811+
3812+
CHECKIF(*ret_conn != NULL) {
3813+
/* This rule helps application developers prevent leaks of connection references. If
3814+
* a bt_conn variable is not null, it presumably holds a reference and must not be
3815+
* overwritten. To avoid this warning, initialize the variables to null, and set
3816+
* them to null when moving the reference.
3817+
*/
3818+
LOG_WRN("*conn should be unreferenced and initialized to NULL");
3819+
3820+
if (IS_ENABLED(CONFIG_BT_CONN_CHECK_NULL_BEFORE_CREATE)) {
3821+
return -EINVAL;
3822+
}
3823+
}
3824+
37913825
err = conn_le_create_common_checks(synced_param->peer, conn_param);
37923826
if (err) {
37933827
return err;

0 commit comments

Comments
 (0)