486 lines
15 KiB
Diff
486 lines
15 KiB
Diff
diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
|
|
--- a/drivers/bluetooth/btintel.c
|
|
+++ b/drivers/bluetooth/btintel.c
|
|
@@ -288,7 +288,8 @@ void btintel_hw_error(struct hci_dev *hdev, u8 code)
|
|
goto unlock;
|
|
}
|
|
|
|
- bt_dev_err(hdev, "Exception info %s", (char *)(skb->data + 1));
|
|
+ bt_dev_err(hdev, "Exception info %.*s", (int)(skb->len - 1),
|
|
+ (char *)(skb->data + 1));
|
|
|
|
kfree_skb(skb);
|
|
|
|
@@ -407,8 +408,16 @@ int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name)
|
|
/* DDC file contains one or more DDC structure which has
|
|
* Length (1 byte), DDC ID (2 bytes), and DDC value (Length - 2).
|
|
*/
|
|
- while (fw->size > fw_ptr - fw->data) {
|
|
- u8 cmd_plen = fw_ptr[0] + sizeof(u8);
|
|
+ while (fw->size > (size_t)(fw_ptr - fw->data)) {
|
|
+ size_t remaining = fw->size - (fw_ptr - fw->data);
|
|
+ unsigned int cmd_plen = fw_ptr[0] + 1U;
|
|
+
|
|
+ if (cmd_plen < 3 || cmd_plen > U8_MAX || cmd_plen > remaining) {
|
|
+ bt_dev_err(hdev, "Malformed DDC record (plen=%u, remaining=%zu)",
|
|
+ cmd_plen, remaining);
|
|
+ release_firmware(fw);
|
|
+ return -EINVAL;
|
|
+ }
|
|
|
|
skb = __hci_cmd_sync(hdev, 0xfc8b, cmd_plen, fw_ptr,
|
|
HCI_INIT_TIMEOUT);
|
|
diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
|
|
--- a/drivers/bluetooth/btintel_pcie.c
|
|
+++ b/drivers/bluetooth/btintel_pcie.c
|
|
@@ -1200,7 +1200,7 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
|
|
{
|
|
int ret;
|
|
u8 pkt_type;
|
|
- u16 plen;
|
|
+ u32 plen;
|
|
u32 pcie_pkt_type;
|
|
void *pdata;
|
|
struct hci_dev *hdev = data->hdev;
|
|
@@ -2149,6 +2149,16 @@ static int btintel_pcie_send_frame(struct hci_dev *hdev,
|
|
if (test_bit(BTINTEL_PCIE_RECOVERY_IN_PROGRESS, &data->flags))
|
|
return -ENODEV;
|
|
|
|
+ /* Account for the 4-byte PCIe type header prepended before the
|
|
+ * DMA copy. Written as a subtraction to avoid wrap-around on
|
|
+ * attacker-controlled skb->len.
|
|
+ */
|
|
+ if (skb->len > BTINTEL_PCIE_BUFFER_SIZE - BTINTEL_PCIE_HCI_TYPE_LEN) {
|
|
+ bt_dev_err(hdev, "Packet too large: %u > %u", skb->len,
|
|
+ BTINTEL_PCIE_BUFFER_SIZE - BTINTEL_PCIE_HCI_TYPE_LEN);
|
|
+ return -EMSGSIZE;
|
|
+ }
|
|
+
|
|
/* Due to the fw limitation, the type header of the packet should be
|
|
* 4 bytes unlike 1 byte for UART. In UART, the firmware can read
|
|
* the first byte to get the packet type and redirect the rest of data
|
|
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
|
|
--- a/include/net/bluetooth/hci_core.h
|
|
+++ b/include/net/bluetooth/hci_core.h
|
|
@@ -62,7 +62,7 @@ struct inquiry_entry {
|
|
NAME_PENDING,
|
|
NAME_KNOWN,
|
|
} name_state;
|
|
- __u32 timestamp;
|
|
+ unsigned long timestamp;
|
|
struct inquiry_data data;
|
|
};
|
|
|
|
@@ -78,7 +78,7 @@ struct discovery_state {
|
|
struct list_head all; /* All devices found during inquiry */
|
|
struct list_head unknown; /* Name state not known */
|
|
struct list_head resolve; /* Name needs to be resolved */
|
|
- __u32 timestamp;
|
|
+ unsigned long timestamp;
|
|
bdaddr_t last_adv_addr;
|
|
u8 last_adv_addr_type;
|
|
s8 last_adv_rssi;
|
|
@@ -561,6 +561,7 @@ struct hci_dev {
|
|
struct list_head link_keys;
|
|
struct list_head long_term_keys;
|
|
struct list_head identity_resolving_keys;
|
|
+ struct mutex remote_oob_lock;
|
|
struct list_head remote_oob_data;
|
|
struct list_head le_accept_list;
|
|
struct list_head le_resolv_list;
|
|
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
|
|
--- a/net/bluetooth/hci_conn.c
|
|
+++ b/net/bluetooth/hci_conn.c
|
|
@@ -302,11 +302,13 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
|
|
cp.tx_bandwidth = cpu_to_le32(0x00001f40);
|
|
cp.rx_bandwidth = cpu_to_le32(0x00001f40);
|
|
|
|
+ hci_dev_lock(hdev);
|
|
+
|
|
switch (conn->codec.id) {
|
|
case BT_CODEC_MSBC:
|
|
if (!find_next_esco_param(conn, esco_param_msbc,
|
|
ARRAY_SIZE(esco_param_msbc)))
|
|
- return -EINVAL;
|
|
+ goto unlock;
|
|
|
|
param = &esco_param_msbc[conn->attempt - 1];
|
|
cp.tx_coding_format.id = 0x05;
|
|
@@ -332,7 +334,7 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
|
|
case BT_CODEC_TRANSPARENT:
|
|
if (!find_next_esco_param(conn, esco_param_msbc,
|
|
ARRAY_SIZE(esco_param_msbc)))
|
|
- return -EINVAL;
|
|
+ goto unlock;
|
|
|
|
param = &esco_param_msbc[conn->attempt - 1];
|
|
cp.tx_coding_format.id = 0x03;
|
|
@@ -359,11 +361,11 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
|
|
if (conn->parent && lmp_esco_capable(conn->parent)) {
|
|
if (!find_next_esco_param(conn, esco_param_cvsd,
|
|
ARRAY_SIZE(esco_param_cvsd)))
|
|
- return -EINVAL;
|
|
+ goto unlock;
|
|
param = &esco_param_cvsd[conn->attempt - 1];
|
|
} else {
|
|
if (conn->attempt > ARRAY_SIZE(sco_param_cvsd))
|
|
- return -EINVAL;
|
|
+ goto unlock;
|
|
param = &sco_param_cvsd[conn->attempt - 1];
|
|
}
|
|
cp.tx_coding_format.id = 2;
|
|
@@ -386,9 +388,11 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
|
|
cp.out_transport_unit_size = 16;
|
|
break;
|
|
default:
|
|
- return -EINVAL;
|
|
+ goto unlock;
|
|
}
|
|
|
|
+ hci_dev_unlock(hdev);
|
|
+
|
|
cp.retrans_effort = param->retrans_effort;
|
|
cp.pkt_type = __cpu_to_le16(param->pkt_type);
|
|
cp.max_latency = __cpu_to_le16(param->max_latency);
|
|
@@ -397,6 +401,10 @@ static int hci_enhanced_setup_sync(struct hci_dev *hdev, void *data)
|
|
return -EIO;
|
|
|
|
return 0;
|
|
+
|
|
+unlock:
|
|
+ hci_dev_unlock(hdev);
|
|
+ return -EINVAL;
|
|
}
|
|
|
|
static bool hci_setup_sync_conn(struct hci_conn *conn, __u16 handle)
|
|
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
|
|
--- a/net/bluetooth/hci_core.c
|
|
+++ b/net/bluetooth/hci_core.c
|
|
@@ -1486,8 +1486,10 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|
|
|
BT_DBG("%s removing %pMR (%u)", hdev->name, bdaddr, bdaddr_type);
|
|
|
|
+ mutex_lock(&hdev->remote_oob_lock);
|
|
list_del(&data->list);
|
|
kfree(data);
|
|
+ mutex_unlock(&hdev->remote_oob_lock);
|
|
|
|
return 0;
|
|
}
|
|
@@ -1496,10 +1498,12 @@ void hci_remote_oob_data_clear(struct hci_dev *hdev)
|
|
{
|
|
struct oob_data *data, *n;
|
|
|
|
+ mutex_lock(&hdev->remote_oob_lock);
|
|
list_for_each_entry_safe(data, n, &hdev->remote_oob_data, list) {
|
|
list_del(&data->list);
|
|
kfree(data);
|
|
}
|
|
+ mutex_unlock(&hdev->remote_oob_lock);
|
|
}
|
|
|
|
int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|
@@ -1508,11 +1512,14 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|
{
|
|
struct oob_data *data;
|
|
|
|
+ mutex_lock(&hdev->remote_oob_lock);
|
|
data = hci_find_remote_oob_data(hdev, bdaddr, bdaddr_type);
|
|
if (!data) {
|
|
data = kmalloc_obj(*data);
|
|
- if (!data)
|
|
+ if (!data) {
|
|
+ mutex_unlock(&hdev->remote_oob_lock);
|
|
return -ENOMEM;
|
|
+ }
|
|
|
|
bacpy(&data->bdaddr, bdaddr);
|
|
data->bdaddr_type = bdaddr_type;
|
|
@@ -1545,6 +1552,8 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
|
|
|
BT_DBG("%s for %pMR", hdev->name, bdaddr);
|
|
|
|
+ mutex_unlock(&hdev->remote_oob_lock);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -2482,6 +2491,7 @@ struct hci_dev *hci_alloc_dev_priv(int sizeof_priv)
|
|
mutex_init(&hdev->lock);
|
|
mutex_init(&hdev->req_lock);
|
|
mutex_init(&hdev->mgmt_pending_lock);
|
|
+ mutex_init(&hdev->remote_oob_lock);
|
|
|
|
ida_init(&hdev->unset_handle_ida);
|
|
|
|
@@ -2554,8 +2564,10 @@ int hci_register_dev(struct hci_dev *hdev)
|
|
return id;
|
|
|
|
error = dev_set_name(&hdev->dev, "hci%u", id);
|
|
- if (error)
|
|
+ if (error) {
|
|
+ ida_free(&hci_index_ida, id);
|
|
return error;
|
|
+ }
|
|
|
|
hdev->name = dev_name(&hdev->dev);
|
|
hdev->id = id;
|
|
@@ -3323,6 +3335,8 @@ static void hci_queue_iso(struct hci_conn *conn, struct sk_buff_head *queue,
|
|
|
|
skb_shinfo(skb)->frag_list = NULL;
|
|
|
|
+ spin_lock_bh(&queue->lock);
|
|
+
|
|
__skb_queue_tail(queue, skb);
|
|
|
|
do {
|
|
@@ -3337,6 +3351,8 @@ static void hci_queue_iso(struct hci_conn *conn, struct sk_buff_head *queue,
|
|
|
|
__skb_queue_tail(queue, skb);
|
|
} while (list);
|
|
+
|
|
+ spin_unlock_bh(&queue->lock);
|
|
}
|
|
|
|
bt_dev_dbg(hdev, "hcon %p queued %d", conn, skb_queue_len(queue));
|
|
@@ -3400,9 +3416,6 @@ static struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type,
|
|
struct hci_conn *conn = NULL, *c;
|
|
unsigned int num = 0, min = ~0;
|
|
|
|
- /* We don't have to lock device here. Connections are always
|
|
- * added and removed with TX task disabled. */
|
|
-
|
|
rcu_read_lock();
|
|
|
|
list_for_each_entry_rcu(c, &h->list, list) {
|
|
@@ -3607,13 +3620,15 @@ static void __check_timeout(struct hci_dev *hdev, unsigned int cnt, u8 type)
|
|
}
|
|
|
|
/* Schedule SCO */
|
|
-static void hci_sched_sco(struct hci_dev *hdev, __u8 type)
|
|
+static void __hci_sched_sco(struct hci_dev *hdev, __u8 type)
|
|
{
|
|
struct hci_conn *conn;
|
|
struct sk_buff *skb;
|
|
int quote, *cnt;
|
|
unsigned int pkts = hdev->sco_pkts;
|
|
|
|
+ lockdep_assert_held(&hdev->lock);
|
|
+
|
|
bt_dev_dbg(hdev, "type %u", type);
|
|
|
|
if (!hci_conn_num(hdev, type) || !pkts)
|
|
@@ -3648,6 +3663,13 @@ static void hci_sched_sco(struct hci_dev *hdev, __u8 type)
|
|
queue_work(hdev->workqueue, &hdev->tx_work);
|
|
}
|
|
|
|
+static void hci_sched_sco(struct hci_dev *hdev, __u8 type)
|
|
+{
|
|
+ hci_dev_lock(hdev);
|
|
+ __hci_sched_sco(hdev, type);
|
|
+ hci_dev_unlock(hdev);
|
|
+}
|
|
+
|
|
static void hci_sched_acl_pkt(struct hci_dev *hdev)
|
|
{
|
|
unsigned int cnt = hdev->acl_cnt;
|
|
@@ -3657,6 +3679,8 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev)
|
|
|
|
__check_timeout(hdev, cnt, ACL_LINK);
|
|
|
|
+ hci_dev_lock(hdev);
|
|
+
|
|
while (hdev->acl_cnt &&
|
|
(chan = hci_chan_sent(hdev, ACL_LINK, "e))) {
|
|
u32 priority = (skb_peek(&chan->data_q))->priority;
|
|
@@ -3681,13 +3705,15 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev)
|
|
chan->conn->sent++;
|
|
|
|
/* Send pending SCO packets right away */
|
|
- hci_sched_sco(hdev, SCO_LINK);
|
|
- hci_sched_sco(hdev, ESCO_LINK);
|
|
+ __hci_sched_sco(hdev, SCO_LINK);
|
|
+ __hci_sched_sco(hdev, ESCO_LINK);
|
|
}
|
|
}
|
|
|
|
if (cnt != hdev->acl_cnt)
|
|
hci_prio_recalculate(hdev, ACL_LINK);
|
|
+
|
|
+ hci_dev_unlock(hdev);
|
|
}
|
|
|
|
static void hci_sched_acl(struct hci_dev *hdev)
|
|
@@ -3716,6 +3742,8 @@ static void hci_sched_le(struct hci_dev *hdev)
|
|
|
|
__check_timeout(hdev, *cnt, LE_LINK);
|
|
|
|
+ hci_dev_lock(hdev);
|
|
+
|
|
tmp = *cnt;
|
|
while (*cnt && (chan = hci_chan_sent(hdev, LE_LINK, "e))) {
|
|
u32 priority = (skb_peek(&chan->data_q))->priority;
|
|
@@ -3737,13 +3765,15 @@ static void hci_sched_le(struct hci_dev *hdev)
|
|
chan->conn->sent++;
|
|
|
|
/* Send pending SCO packets right away */
|
|
- hci_sched_sco(hdev, SCO_LINK);
|
|
- hci_sched_sco(hdev, ESCO_LINK);
|
|
+ __hci_sched_sco(hdev, SCO_LINK);
|
|
+ __hci_sched_sco(hdev, ESCO_LINK);
|
|
}
|
|
}
|
|
|
|
if (*cnt != tmp)
|
|
hci_prio_recalculate(hdev, LE_LINK);
|
|
+
|
|
+ hci_dev_unlock(hdev);
|
|
}
|
|
|
|
/* Schedule iso */
|
|
@@ -3762,6 +3792,8 @@ static void hci_sched_iso(struct hci_dev *hdev, __u8 type)
|
|
|
|
__check_timeout(hdev, *cnt, type);
|
|
|
|
+ hci_dev_lock(hdev);
|
|
+
|
|
while (*cnt && (conn = hci_low_sent(hdev, type, "e))) {
|
|
while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
|
|
BT_DBG("skb %p len %d", skb, skb->len);
|
|
@@ -3775,6 +3807,8 @@ static void hci_sched_iso(struct hci_dev *hdev, __u8 type)
|
|
(*cnt)--;
|
|
}
|
|
}
|
|
+
|
|
+ hci_dev_unlock(hdev);
|
|
}
|
|
|
|
static void hci_tx_work(struct work_struct *work)
|
|
diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c
|
|
--- a/net/bluetooth/hci_debugfs.c
|
|
+++ b/net/bluetooth/hci_debugfs.c
|
|
@@ -364,7 +364,7 @@ static int inquiry_cache_show(struct seq_file *f, void *p)
|
|
|
|
list_for_each_entry(e, &cache->all, all) {
|
|
struct inquiry_data *data = &e->data;
|
|
- seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
|
|
+ seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %lu\n",
|
|
&data->bdaddr,
|
|
data->pscan_rep_mode, data->pscan_period_mode,
|
|
data->pscan_mode, data->dev_class[2],
|
|
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
|
|
--- a/net/bluetooth/hci_sync.c
|
|
+++ b/net/bluetooth/hci_sync.c
|
|
@@ -312,6 +312,10 @@ static void hci_cmd_sync_work(struct work_struct *work)
|
|
while (1) {
|
|
struct hci_cmd_sync_work_entry *entry;
|
|
|
|
+ /* Leave the backlog to hci_cmd_sync_clear() */
|
|
+ if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
|
|
+ break;
|
|
+
|
|
mutex_lock(&hdev->cmd_sync_work_lock);
|
|
entry = list_first_entry_or_null(&hdev->cmd_sync_work_list,
|
|
struct hci_cmd_sync_work_entry,
|
|
@@ -658,6 +662,8 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)
|
|
{
|
|
struct hci_cmd_sync_work_entry *entry, *tmp;
|
|
|
|
+ /* cmd_work is disabled, the pending request can only time out */
|
|
+ hci_cmd_sync_cancel_sync(hdev, ENODEV);
|
|
cancel_work_sync(&hdev->cmd_sync_work);
|
|
cancel_work_sync(&hdev->reenable_adv_work);
|
|
|
|
@@ -5678,6 +5684,7 @@ int hci_stop_discovery_sync(struct hci_dev *hdev)
|
|
{
|
|
struct discovery_state *d = &hdev->discovery;
|
|
struct inquiry_entry *e;
|
|
+ bdaddr_t addr;
|
|
int err;
|
|
|
|
bt_dev_dbg(hdev, "state %u", hdev->discovery.state);
|
|
@@ -5713,15 +5720,21 @@ int hci_stop_discovery_sync(struct hci_dev *hdev)
|
|
return 0;
|
|
|
|
if (d->state == DISCOVERY_RESOLVING || d->state == DISCOVERY_STOPPING) {
|
|
+ hci_dev_lock(hdev);
|
|
e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
|
|
NAME_PENDING);
|
|
- if (!e)
|
|
+ if (!e) {
|
|
+ hci_dev_unlock(hdev);
|
|
return 0;
|
|
+ }
|
|
+
|
|
+ bacpy(&addr, &e->data.bdaddr);
|
|
+ hci_dev_unlock(hdev);
|
|
|
|
/* Ignore cancel errors since it should interfere with stopping
|
|
* of the discovery.
|
|
*/
|
|
- hci_remote_name_cancel_sync(hdev, &e->data.bdaddr);
|
|
+ hci_remote_name_cancel_sync(hdev, &addr);
|
|
}
|
|
|
|
return 0;
|
|
@@ -7151,6 +7164,7 @@ static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data)
|
|
bacpy(&cp.bdaddr, &conn->dst);
|
|
cp.pscan_rep_mode = 0x02;
|
|
|
|
+ hci_dev_lock(hdev);
|
|
ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
|
|
if (ie) {
|
|
if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
|
|
@@ -7162,6 +7176,7 @@ static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data)
|
|
|
|
memcpy(conn->dev_class, ie->data.dev_class, 3);
|
|
}
|
|
+ hci_dev_unlock(hdev);
|
|
|
|
cp.pkt_type = cpu_to_le16(conn->pkt_type);
|
|
if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
|
|
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
|
|
--- a/net/bluetooth/rfcomm/tty.c
|
|
+++ b/net/bluetooth/rfcomm/tty.c
|
|
@@ -462,7 +462,7 @@ static int __rfcomm_release_dev(void __user *arg)
|
|
/* Shut down TTY synchronously before freeing rfcomm_dev */
|
|
tty_port_tty_vhangup(&dev->port);
|
|
|
|
- if (!test_bit(RFCOMM_TTY_OWNED, &dev->status))
|
|
+ if (!test_and_set_bit(RFCOMM_TTY_OWNED, &dev->status))
|
|
tty_port_put(&dev->port);
|
|
|
|
tty_port_put(&dev->port);
|
|
@@ -724,10 +724,9 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
|
|
* when the last process closes the tty. The behaviour is expected by
|
|
* userspace.
|
|
*/
|
|
- if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
|
|
- set_bit(RFCOMM_TTY_OWNED, &dev->status);
|
|
+ if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
|
|
+ !test_and_set_bit(RFCOMM_TTY_OWNED, &dev->status))
|
|
tty_port_put(&dev->port);
|
|
- }
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
|
|
--- a/net/bluetooth/smp.c
|
|
+++ b/net/bluetooth/smp.c
|
|
@@ -661,6 +661,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
|
|
else
|
|
bdaddr_type = BDADDR_LE_RANDOM;
|
|
|
|
+ mutex_lock(&hdev->remote_oob_lock);
|
|
oob_data = hci_find_remote_oob_data(hdev, &hcon->dst,
|
|
bdaddr_type);
|
|
if (oob_data && oob_data->present) {
|
|
@@ -671,6 +672,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
|
|
SMP_DBG("OOB Remote Confirmation: %16phN", smp->pcnf);
|
|
SMP_DBG("OOB Remote Random: %16phN", smp->rr);
|
|
}
|
|
+ mutex_unlock(&hdev->remote_oob_lock);
|
|
|
|
} else {
|
|
authreq &= ~SMP_AUTH_SC;
|