Skip to content

Commit f2d8590

Browse files
committed
Merge tag 'for-net-2024-05-03' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth
Luiz Augusto von Dentz says: ==================== bluetooth pull request for net: - mediatek: mt8183-pico6: Fix bluetooth node - sco: Fix use-after-free bugs caused by sco_sock_timeout - l2cap: fix null-ptr-deref in l2cap_chan_timeout - qca: Various fixes - l2cap: Fix slab-use-after-free in l2cap_connect() - msft: fix slab-use-after-free in msft_do_close() - HCI: Fix potential null-ptr-deref * tag 'for-net-2024-05-03' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth: Bluetooth: qca: fix firmware check error path Bluetooth: l2cap: fix null-ptr-deref in l2cap_chan_timeout Bluetooth: HCI: Fix potential null-ptr-deref arm64: dts: mediatek: mt8183-pico6: Fix bluetooth node Bluetooth: qca: fix info leak when fetching board id Bluetooth: qca: fix info leak when fetching fw build id Bluetooth: qca: generalise device address check Bluetooth: qca: fix NVM configuration parsing Bluetooth: qca: add missing firmware sanity checks Bluetooth: msft: fix slab-use-after-free in msft_do_close() Bluetooth: L2CAP: Fix slab-use-after-free in l2cap_connect() Bluetooth: qca: fix wcn3991 device address check Bluetooth: Fix use-after-free bugs caused by sco_sock_timeout ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents e086363 + 40d442f commit f2d8590

File tree

9 files changed

+119
-36
lines changed

9 files changed

+119
-36
lines changed

arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-pico6.dts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@
8282
};
8383

8484
&mmc1 {
85-
bt_reset: bt-reset {
85+
bluetooth@2 {
86+
reg = <2>;
8687
compatible = "mediatek,mt7921s-bluetooth";
8788
pinctrl-names = "default";
8889
pinctrl-0 = <&bt_pins_reset>;

drivers/bluetooth/btqca.c

Lines changed: 92 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515

1616
#define VERSION "0.1"
1717

18-
#define QCA_BDADDR_DEFAULT (&(bdaddr_t) {{ 0xad, 0x5a, 0x00, 0x00, 0x00, 0x00 }})
19-
2018
int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver,
2119
enum qca_btsoc_type soc_type)
2220
{
@@ -101,7 +99,8 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
10199
{
102100
struct sk_buff *skb;
103101
struct edl_event_hdr *edl;
104-
char cmd, build_label[QCA_FW_BUILD_VER_LEN];
102+
char *build_label;
103+
char cmd;
105104
int build_lbl_len, err = 0;
106105

107106
bt_dev_dbg(hdev, "QCA read fw build info");
@@ -116,6 +115,11 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
116115
return err;
117116
}
118117

118+
if (skb->len < sizeof(*edl)) {
119+
err = -EILSEQ;
120+
goto out;
121+
}
122+
119123
edl = (struct edl_event_hdr *)(skb->data);
120124
if (!edl) {
121125
bt_dev_err(hdev, "QCA read fw build info with no header");
@@ -131,14 +135,25 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
131135
goto out;
132136
}
133137

138+
if (skb->len < sizeof(*edl) + 1) {
139+
err = -EILSEQ;
140+
goto out;
141+
}
142+
134143
build_lbl_len = edl->data[0];
135-
if (build_lbl_len <= QCA_FW_BUILD_VER_LEN - 1) {
136-
memcpy(build_label, edl->data + 1, build_lbl_len);
137-
*(build_label + build_lbl_len) = '\0';
144+
145+
if (skb->len < sizeof(*edl) + 1 + build_lbl_len) {
146+
err = -EILSEQ;
147+
goto out;
138148
}
139149

150+
build_label = kstrndup(&edl->data[1], build_lbl_len, GFP_KERNEL);
151+
if (!build_label)
152+
goto out;
153+
140154
hci_set_fw_info(hdev, "%s", build_label);
141155

156+
kfree(build_label);
142157
out:
143158
kfree_skb(skb);
144159
return err;
@@ -237,6 +252,11 @@ static int qca_read_fw_board_id(struct hci_dev *hdev, u16 *bid)
237252
goto out;
238253
}
239254

255+
if (skb->len < 3) {
256+
err = -EILSEQ;
257+
goto out;
258+
}
259+
240260
*bid = (edl->data[1] << 8) + edl->data[2];
241261
bt_dev_dbg(hdev, "%s: bid = %x", __func__, *bid);
242262

@@ -267,9 +287,10 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
267287
}
268288
EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
269289

270-
static void qca_tlv_check_data(struct hci_dev *hdev,
290+
static int qca_tlv_check_data(struct hci_dev *hdev,
271291
struct qca_fw_config *config,
272-
u8 *fw_data, enum qca_btsoc_type soc_type)
292+
u8 *fw_data, size_t fw_size,
293+
enum qca_btsoc_type soc_type)
273294
{
274295
const u8 *data;
275296
u32 type_len;
@@ -279,12 +300,16 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
279300
struct tlv_type_patch *tlv_patch;
280301
struct tlv_type_nvm *tlv_nvm;
281302
uint8_t nvm_baud_rate = config->user_baud_rate;
303+
u8 type;
282304

283305
config->dnld_mode = QCA_SKIP_EVT_NONE;
284306
config->dnld_type = QCA_SKIP_EVT_NONE;
285307

286308
switch (config->type) {
287309
case ELF_TYPE_PATCH:
310+
if (fw_size < 7)
311+
return -EINVAL;
312+
288313
config->dnld_mode = QCA_SKIP_EVT_VSE_CC;
289314
config->dnld_type = QCA_SKIP_EVT_VSE_CC;
290315

@@ -293,6 +318,9 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
293318
bt_dev_dbg(hdev, "File version : 0x%x", fw_data[6]);
294319
break;
295320
case TLV_TYPE_PATCH:
321+
if (fw_size < sizeof(struct tlv_type_hdr) + sizeof(struct tlv_type_patch))
322+
return -EINVAL;
323+
296324
tlv = (struct tlv_type_hdr *)fw_data;
297325
type_len = le32_to_cpu(tlv->type_len);
298326
tlv_patch = (struct tlv_type_patch *)tlv->data;
@@ -332,25 +360,64 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
332360
break;
333361

334362
case TLV_TYPE_NVM:
363+
if (fw_size < sizeof(struct tlv_type_hdr))
364+
return -EINVAL;
365+
335366
tlv = (struct tlv_type_hdr *)fw_data;
336367

337368
type_len = le32_to_cpu(tlv->type_len);
338-
length = (type_len >> 8) & 0x00ffffff;
369+
length = type_len >> 8;
370+
type = type_len & 0xff;
339371

340-
BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x000000ff);
372+
/* Some NVM files have more than one set of tags, only parse
373+
* the first set when it has type 2 for now. When there is
374+
* more than one set there is an enclosing header of type 4.
375+
*/
376+
if (type == 4) {
377+
if (fw_size < 2 * sizeof(struct tlv_type_hdr))
378+
return -EINVAL;
379+
380+
tlv++;
381+
382+
type_len = le32_to_cpu(tlv->type_len);
383+
length = type_len >> 8;
384+
type = type_len & 0xff;
385+
}
386+
387+
BT_DBG("TLV Type\t\t : 0x%x", type);
341388
BT_DBG("Length\t\t : %d bytes", length);
342389

390+
if (type != 2)
391+
break;
392+
393+
if (fw_size < length + (tlv->data - fw_data))
394+
return -EINVAL;
395+
343396
idx = 0;
344397
data = tlv->data;
345-
while (idx < length) {
398+
while (idx < length - sizeof(struct tlv_type_nvm)) {
346399
tlv_nvm = (struct tlv_type_nvm *)(data + idx);
347400

348401
tag_id = le16_to_cpu(tlv_nvm->tag_id);
349402
tag_len = le16_to_cpu(tlv_nvm->tag_len);
350403

404+
if (length < idx + sizeof(struct tlv_type_nvm) + tag_len)
405+
return -EINVAL;
406+
351407
/* Update NVM tags as needed */
352408
switch (tag_id) {
409+
case EDL_TAG_ID_BD_ADDR:
410+
if (tag_len != sizeof(bdaddr_t))
411+
return -EINVAL;
412+
413+
memcpy(&config->bdaddr, tlv_nvm->data, sizeof(bdaddr_t));
414+
415+
break;
416+
353417
case EDL_TAG_ID_HCI:
418+
if (tag_len < 3)
419+
return -EINVAL;
420+
354421
/* HCI transport layer parameters
355422
* enabling software inband sleep
356423
* onto controller side.
@@ -366,6 +433,9 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
366433
break;
367434

368435
case EDL_TAG_ID_DEEP_SLEEP:
436+
if (tag_len < 1)
437+
return -EINVAL;
438+
369439
/* Sleep enable mask
370440
* enabling deep sleep feature on controller.
371441
*/
@@ -374,14 +444,16 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
374444
break;
375445
}
376446

377-
idx += (sizeof(u16) + sizeof(u16) + 8 + tag_len);
447+
idx += sizeof(struct tlv_type_nvm) + tag_len;
378448
}
379449
break;
380450

381451
default:
382452
BT_ERR("Unknown TLV type %d", config->type);
383-
break;
453+
return -EINVAL;
384454
}
455+
456+
return 0;
385457
}
386458

387459
static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size,
@@ -531,7 +603,9 @@ static int qca_download_firmware(struct hci_dev *hdev,
531603
memcpy(data, fw->data, size);
532604
release_firmware(fw);
533605

534-
qca_tlv_check_data(hdev, config, data, soc_type);
606+
ret = qca_tlv_check_data(hdev, config, data, size, soc_type);
607+
if (ret)
608+
goto out;
535609

536610
segment = data;
537611
remain = size;
@@ -614,7 +688,7 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
614688
}
615689
EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
616690

617-
static int qca_check_bdaddr(struct hci_dev *hdev)
691+
static int qca_check_bdaddr(struct hci_dev *hdev, const struct qca_fw_config *config)
618692
{
619693
struct hci_rp_read_bd_addr *bda;
620694
struct sk_buff *skb;
@@ -638,7 +712,7 @@ static int qca_check_bdaddr(struct hci_dev *hdev)
638712
}
639713

640714
bda = (struct hci_rp_read_bd_addr *)skb->data;
641-
if (!bacmp(&bda->bdaddr, QCA_BDADDR_DEFAULT))
715+
if (!bacmp(&bda->bdaddr, &config->bdaddr))
642716
set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
643717

644718
kfree_skb(skb);
@@ -667,7 +741,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
667741
enum qca_btsoc_type soc_type, struct qca_btsoc_version ver,
668742
const char *firmware_name)
669743
{
670-
struct qca_fw_config config;
744+
struct qca_fw_config config = {};
671745
int err;
672746
u8 rom_ver = 0;
673747
u32 soc_ver;
@@ -852,7 +926,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
852926
break;
853927
}
854928

855-
err = qca_check_bdaddr(hdev);
929+
err = qca_check_bdaddr(hdev, &config);
856930
if (err)
857931
return err;
858932

drivers/bluetooth/btqca.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#define EDL_PATCH_CONFIG_RES_EVT (0x00)
3030
#define QCA_DISABLE_LOGGING_SUB_OP (0x14)
3131

32+
#define EDL_TAG_ID_BD_ADDR 2
3233
#define EDL_TAG_ID_HCI (17)
3334
#define EDL_TAG_ID_DEEP_SLEEP (27)
3435

@@ -47,7 +48,6 @@
4748
#define get_soc_ver(soc_id, rom_ver) \
4849
((le32_to_cpu(soc_id) << 16) | (le16_to_cpu(rom_ver)))
4950

50-
#define QCA_FW_BUILD_VER_LEN 255
5151
#define QCA_HSP_GF_SOC_ID 0x1200
5252
#define QCA_HSP_GF_SOC_MASK 0x0000ff00
5353

@@ -94,6 +94,7 @@ struct qca_fw_config {
9494
uint8_t user_baud_rate;
9595
enum qca_tlv_dnld_mode dnld_mode;
9696
enum qca_tlv_dnld_mode dnld_type;
97+
bdaddr_t bdaddr;
9798
};
9899

99100
struct edl_event_hdr {

net/bluetooth/hci_core.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2768,8 +2768,6 @@ void hci_unregister_dev(struct hci_dev *hdev)
27682768

27692769
hci_unregister_suspend_notifier(hdev);
27702770

2771-
msft_unregister(hdev);
2772-
27732771
hci_dev_do_close(hdev);
27742772

27752773
if (!test_bit(HCI_INIT, &hdev->flags) &&
@@ -2823,6 +2821,7 @@ void hci_release_dev(struct hci_dev *hdev)
28232821
hci_discovery_filter_clear(hdev);
28242822
hci_blocked_keys_clear(hdev);
28252823
hci_codec_list_clear(&hdev->local_codecs);
2824+
msft_release(hdev);
28262825
hci_dev_unlock(hdev);
28272826

28282827
ida_destroy(&hdev->unset_handle_ida);

net/bluetooth/hci_event.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7037,6 +7037,8 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
70377037
u16 handle = le16_to_cpu(ev->bis[i]);
70387038

70397039
bis = hci_conn_hash_lookup_handle(hdev, handle);
7040+
if (!bis)
7041+
continue;
70407042

70417043
set_bit(HCI_CONN_BIG_SYNC_FAILED, &bis->flags);
70427044
hci_connect_cfm(bis, ev->status);

net/bluetooth/l2cap_core.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,9 @@ static void l2cap_chan_timeout(struct work_struct *work)
415415

416416
BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
417417

418+
if (!conn)
419+
return;
420+
418421
mutex_lock(&conn->chan_lock);
419422
/* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
420423
* this work. No need to call l2cap_chan_hold(chan) here again.
@@ -3902,13 +3905,12 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn,
39023905
return 0;
39033906
}
39043907

3905-
static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
3906-
struct l2cap_cmd_hdr *cmd,
3907-
u8 *data, u8 rsp_code, u8 amp_id)
3908+
static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
3909+
u8 *data, u8 rsp_code, u8 amp_id)
39083910
{
39093911
struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
39103912
struct l2cap_conn_rsp rsp;
3911-
struct l2cap_chan *chan = NULL, *pchan;
3913+
struct l2cap_chan *chan = NULL, *pchan = NULL;
39123914
int result, status = L2CAP_CS_NO_INFO;
39133915

39143916
u16 dcid = 0, scid = __le16_to_cpu(req->scid);
@@ -3921,7 +3923,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
39213923
&conn->hcon->dst, ACL_LINK);
39223924
if (!pchan) {
39233925
result = L2CAP_CR_BAD_PSM;
3924-
goto sendresp;
3926+
goto response;
39253927
}
39263928

39273929
mutex_lock(&conn->chan_lock);
@@ -4008,17 +4010,15 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
40084010
}
40094011

40104012
response:
4011-
l2cap_chan_unlock(pchan);
4012-
mutex_unlock(&conn->chan_lock);
4013-
l2cap_chan_put(pchan);
4014-
4015-
sendresp:
40164013
rsp.scid = cpu_to_le16(scid);
40174014
rsp.dcid = cpu_to_le16(dcid);
40184015
rsp.result = cpu_to_le16(result);
40194016
rsp.status = cpu_to_le16(status);
40204017
l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
40214018

4019+
if (!pchan)
4020+
return;
4021+
40224022
if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
40234023
struct l2cap_info_req info;
40244024
info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
@@ -4041,7 +4041,9 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
40414041
chan->num_conf_req++;
40424042
}
40434043

4044-
return chan;
4044+
l2cap_chan_unlock(pchan);
4045+
mutex_unlock(&conn->chan_lock);
4046+
l2cap_chan_put(pchan);
40454047
}
40464048

40474049
static int l2cap_connect_req(struct l2cap_conn *conn,

net/bluetooth/msft.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ void msft_register(struct hci_dev *hdev)
769769
mutex_init(&msft->filter_lock);
770770
}
771771

772-
void msft_unregister(struct hci_dev *hdev)
772+
void msft_release(struct hci_dev *hdev)
773773
{
774774
struct msft_data *msft = hdev->msft_data;
775775

0 commit comments

Comments
 (0)