mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 15:22:21 -04:00
Bluetooth: MGMT: free the HCI command when it is cancelled
mgmt_hci_cmd_sync() queues the pending command with a NULL destroy
callback, so it is only freed if send_hci_cmd_sync() runs. A cancelled
entry is leaked, as _hci_cmd_sync_cancel_entry() does not release
entry->data when there is no destroy callback, and hci_cmd_sync_clear()
cancels every pending entry when the controller is unregistered. Nothing
else reclaims it either: mgmt_pending_new() does not put the command on
hdev->mgmt_pending.
The leak also pins the socket reference taken by mgmt_pending_new(), so
the mgmt socket is never released.
Free the command from a destroy callback. The now-empty done label is
replaced by a direct return.
Fixes: 827af4787e ("Bluetooth: MGMT: Add initial implementation of MGMT_OP_HCI_CMD_SYNC")
Signed-off-by: Linmao Li <lilinmao@kylinos.cn>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
committed by
Luiz Augusto von Dentz
parent
3c742feda8
commit
414b365ece
@@ -2653,7 +2653,7 @@ static int send_hci_cmd_sync(struct hci_dev *hdev, void *data)
|
||||
if (IS_ERR(skb)) {
|
||||
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_HCI_CMD_SYNC,
|
||||
mgmt_status(PTR_ERR(skb)));
|
||||
goto done;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_HCI_CMD_SYNC, 0,
|
||||
@@ -2661,12 +2661,14 @@ static int send_hci_cmd_sync(struct hci_dev *hdev, void *data)
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
done:
|
||||
mgmt_pending_free(cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void send_hci_cmd_sync_destroy(struct hci_dev *hdev, void *data, int err)
|
||||
{
|
||||
mgmt_pending_free(data);
|
||||
}
|
||||
|
||||
static int mgmt_hci_cmd_sync(struct sock *sk, struct hci_dev *hdev,
|
||||
void *data, u16 len)
|
||||
{
|
||||
@@ -2684,7 +2686,8 @@ static int mgmt_hci_cmd_sync(struct sock *sk, struct hci_dev *hdev,
|
||||
if (!cmd)
|
||||
err = -ENOMEM;
|
||||
else
|
||||
err = hci_cmd_sync_queue(hdev, send_hci_cmd_sync, cmd, NULL);
|
||||
err = hci_cmd_sync_queue(hdev, send_hci_cmd_sync, cmd,
|
||||
send_hci_cmd_sync_destroy);
|
||||
|
||||
if (err < 0) {
|
||||
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_HCI_CMD_SYNC,
|
||||
|
||||
Reference in New Issue
Block a user