Skip to content

Commit 1088814

Browse files
arndbholtmann
authored andcommitted
Bluetooth: btusb: fix excessive stack usage
Enlarging the size of 'struct btmtk_hci_wmt_cmd' makes it no longer fit on the kernel stack, as seen from this compiler warning: drivers/bluetooth/btusb.c:3365:12: error: stack frame size of 1036 bytes in function 'btusb_mtk_hci_wmt_sync' [-Werror,-Wframe-larger-than=] Change the function to dynamically allocate the buffer instead. As there are other sleeping functions called from the same location, using GFP_KERNEL should be fine here, and the runtime overhead should not matter as this is rarely called. Unfortunately, I could not figure out why the message size is increased in the previous patch. Using dynamic allocation means any size is possible now, but there is still a range check that limits the total size (including the five-byte header) to 255 bytes, so whatever was intended there is now undone. Fixes: 48c1330 ("Bluetooth: btusb: Fine-tune mt7663 mechanism.") Signed-off-by: Arnd Bergmann <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent 8564baa commit 1088814

File tree

1 file changed

+15
-9
lines changed

1 file changed

+15
-9
lines changed

drivers/bluetooth/btusb.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3161,7 +3161,7 @@ struct btmtk_wmt_hdr {
31613161

31623162
struct btmtk_hci_wmt_cmd {
31633163
struct btmtk_wmt_hdr hdr;
3164-
u8 data[1000];
3164+
u8 data[];
31653165
} __packed;
31663166

31673167
struct btmtk_hci_wmt_evt {
@@ -3369,7 +3369,7 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
33693369
struct btmtk_hci_wmt_evt_funcc *wmt_evt_funcc;
33703370
u32 hlen, status = BTMTK_WMT_INVALID;
33713371
struct btmtk_hci_wmt_evt *wmt_evt;
3372-
struct btmtk_hci_wmt_cmd wc;
3372+
struct btmtk_hci_wmt_cmd *wc;
33733373
struct btmtk_wmt_hdr *hdr;
33743374
int err;
33753375

@@ -3383,20 +3383,24 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
33833383
if (hlen > 255)
33843384
return -EINVAL;
33853385

3386-
hdr = (struct btmtk_wmt_hdr *)&wc;
3386+
wc = kzalloc(hlen, GFP_KERNEL);
3387+
if (!wc)
3388+
return -ENOMEM;
3389+
3390+
hdr = &wc->hdr;
33873391
hdr->dir = 1;
33883392
hdr->op = wmt_params->op;
33893393
hdr->dlen = cpu_to_le16(wmt_params->dlen + 1);
33903394
hdr->flag = wmt_params->flag;
3391-
memcpy(wc.data, wmt_params->data, wmt_params->dlen);
3395+
memcpy(wc->data, wmt_params->data, wmt_params->dlen);
33923396

33933397
set_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
33943398

3395-
err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc);
3399+
err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc);
33963400

33973401
if (err < 0) {
33983402
clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
3399-
return err;
3403+
goto err_free_wc;
34003404
}
34013405

34023406
/* The vendor specific WMT commands are all answered by a vendor
@@ -3413,13 +3417,14 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
34133417
if (err == -EINTR) {
34143418
bt_dev_err(hdev, "Execution of wmt command interrupted");
34153419
clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
3416-
return err;
3420+
goto err_free_wc;
34173421
}
34183422

34193423
if (err) {
34203424
bt_dev_err(hdev, "Execution of wmt command timed out");
34213425
clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags);
3422-
return -ETIMEDOUT;
3426+
err = -ETIMEDOUT;
3427+
goto err_free_wc;
34233428
}
34243429

34253430
/* Parse and handle the return WMT event */
@@ -3463,7 +3468,8 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev,
34633468
err_free_skb:
34643469
kfree_skb(data->evt_skb);
34653470
data->evt_skb = NULL;
3466-
3471+
err_free_wc:
3472+
kfree(wc);
34673473
return err;
34683474
}
34693475

0 commit comments

Comments
 (0)