Update Linux kernel release to v7.2.8-2 for base and BORE kernels
Signed-off-by: Krzysztof Wilczyński <kwilczynski@omarchy.org>
This commit is contained in:
524 files changed
+147294
-88760
No files matched your search
@@ -0,0 +1,485 @@
|
||||
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;
|
||||
Reference in new issue
Block a user