Bluetooth: Fix deadlock-risky HCI command buffer allocation
The LE scanning and advertising implementations were allocating and holding buffers (the scan & advertising parameters respectively) while at the same time potentially sending other commands (such as setting the local private address). If these APIs would end up being called simultaneously from different contexts, this could lead to a deadlock in trying to allocate HCI command buffers, especially considering that the default HCI command buffer count is 2. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
446503dc50
commit
68f6b59e2d
1 changed files with 34 additions and 41 deletions
|
@ -2887,41 +2887,32 @@ static void hci_cmd_status(struct net_buf *buf)
|
|||
|
||||
static int start_le_scan(u8_t scan_type, u16_t interval, u16_t window)
|
||||
{
|
||||
struct bt_hci_cp_le_set_scan_param *set_param;
|
||||
struct bt_hci_cp_le_set_scan_param set_param;
|
||||
struct net_buf *buf;
|
||||
int err;
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_PARAM,
|
||||
sizeof(*set_param));
|
||||
if (!buf) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
set_param = net_buf_add(buf, sizeof(*set_param));
|
||||
memset(set_param, 0, sizeof(*set_param));
|
||||
set_param->scan_type = scan_type;
|
||||
set_param.scan_type = scan_type;
|
||||
|
||||
/* for the rest parameters apply default values according to
|
||||
* spec 4.2, vol2, part E, 7.8.10
|
||||
*/
|
||||
set_param->interval = sys_cpu_to_le16(interval);
|
||||
set_param->window = sys_cpu_to_le16(window);
|
||||
set_param->filter_policy = 0x00;
|
||||
set_param.interval = sys_cpu_to_le16(interval);
|
||||
set_param.window = sys_cpu_to_le16(window);
|
||||
set_param.filter_policy = 0x00;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_PRIVACY)) {
|
||||
err = le_set_private_addr();
|
||||
if (err) {
|
||||
net_buf_unref(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) {
|
||||
set_param->addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM;
|
||||
set_param.addr_type = BT_HCI_OWN_ADDR_RPA_OR_RANDOM;
|
||||
} else {
|
||||
set_param->addr_type = BT_ADDR_LE_RANDOM;
|
||||
set_param.addr_type = BT_ADDR_LE_RANDOM;
|
||||
}
|
||||
} else {
|
||||
set_param->addr_type = bt_dev.id_addr.type;
|
||||
set_param.addr_type = bt_dev.id_addr.type;
|
||||
|
||||
/* Use NRPA unless identity has been explicitly requested
|
||||
* (through Kconfig), or if there is no advertising ongoing.
|
||||
|
@ -2931,14 +2922,20 @@ static int start_le_scan(u8_t scan_type, u16_t interval, u16_t window)
|
|||
!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) {
|
||||
err = le_set_private_addr();
|
||||
if (err) {
|
||||
net_buf_unref(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
set_param->addr_type = BT_ADDR_LE_RANDOM;
|
||||
set_param.addr_type = BT_ADDR_LE_RANDOM;
|
||||
}
|
||||
}
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_PARAM, sizeof(set_param));
|
||||
if (!buf) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
net_buf_add_mem(buf, &set_param, sizeof(set_param));
|
||||
|
||||
bt_hci_cmd_send(BT_HCI_OP_LE_SET_SCAN_PARAM, buf);
|
||||
|
||||
err = set_le_scan_enable(BT_HCI_LE_SCAN_ENABLE);
|
||||
|
@ -4616,8 +4613,8 @@ int bt_le_adv_start(const struct bt_le_adv_param *param,
|
|||
const struct bt_data *ad, size_t ad_len,
|
||||
const struct bt_data *sd, size_t sd_len)
|
||||
{
|
||||
struct bt_hci_cp_le_set_adv_param set_param;
|
||||
struct net_buf *buf;
|
||||
struct bt_hci_cp_le_set_adv_param *set_param;
|
||||
int err;
|
||||
|
||||
if (!valid_adv_param(param)) {
|
||||
|
@ -4649,32 +4646,22 @@ int bt_le_adv_start(const struct bt_le_adv_param *param,
|
|||
}
|
||||
}
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM,
|
||||
sizeof(*set_param));
|
||||
if (!buf) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
set_param = net_buf_add(buf, sizeof(*set_param));
|
||||
|
||||
memset(set_param, 0, sizeof(*set_param));
|
||||
set_param->min_interval = sys_cpu_to_le16(param->interval_min);
|
||||
set_param->max_interval = sys_cpu_to_le16(param->interval_max);
|
||||
set_param->channel_map = 0x07;
|
||||
set_param.min_interval = sys_cpu_to_le16(param->interval_min);
|
||||
set_param.max_interval = sys_cpu_to_le16(param->interval_max);
|
||||
set_param.channel_map = 0x07;
|
||||
|
||||
if (param->options & BT_LE_ADV_OPT_CONNECTABLE) {
|
||||
if (IS_ENABLED(CONFIG_BT_PRIVACY)) {
|
||||
err = le_set_private_addr();
|
||||
if (err) {
|
||||
net_buf_unref(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (BT_FEAT_LE_PRIVACY(bt_dev.le.features)) {
|
||||
set_param->own_addr_type =
|
||||
set_param.own_addr_type =
|
||||
BT_HCI_OWN_ADDR_RPA_OR_RANDOM;
|
||||
} else {
|
||||
set_param->own_addr_type = BT_ADDR_LE_RANDOM;
|
||||
set_param.own_addr_type = BT_ADDR_LE_RANDOM;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
|
@ -4688,10 +4675,10 @@ int bt_le_adv_start(const struct bt_le_adv_param *param,
|
|||
set_random_address(&bt_dev.id_addr.a);
|
||||
}
|
||||
|
||||
set_param->own_addr_type = bt_dev.id_addr.type;
|
||||
set_param.own_addr_type = bt_dev.id_addr.type;
|
||||
}
|
||||
|
||||
set_param->type = BT_LE_ADV_IND;
|
||||
set_param.type = BT_LE_ADV_IND;
|
||||
} else {
|
||||
if (param->own_addr) {
|
||||
/* Only NRPA is allowed */
|
||||
|
@ -4705,19 +4692,25 @@ int bt_le_adv_start(const struct bt_le_adv_param *param,
|
|||
}
|
||||
|
||||
if (err) {
|
||||
net_buf_unref(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
set_param->own_addr_type = BT_ADDR_LE_RANDOM;
|
||||
set_param.own_addr_type = BT_ADDR_LE_RANDOM;
|
||||
|
||||
if (sd) {
|
||||
set_param->type = BT_LE_ADV_SCAN_IND;
|
||||
set_param.type = BT_LE_ADV_SCAN_IND;
|
||||
} else {
|
||||
set_param->type = BT_LE_ADV_NONCONN_IND;
|
||||
set_param.type = BT_LE_ADV_NONCONN_IND;
|
||||
}
|
||||
}
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param));
|
||||
if (!buf) {
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
net_buf_add_mem(buf, &set_param, sizeof(set_param));
|
||||
|
||||
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_PARAM, buf, NULL);
|
||||
if (err) {
|
||||
return err;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue