Bluetooth: MGMT: free the mesh send cancel command when it is cancelled

mesh_send_cancel() queues the pending command with a NULL destroy
callback, so it is only freed if send_cancel() 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.

Fixes: b338d91703 ("Bluetooth: Implement support for Mesh")
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:
Linmao Li
2026-08-06 20:59:56 +08:00
committed by Luiz Augusto von Dentz
parent 120d8dc042
commit 3c742feda8

View File

@@ -2437,11 +2437,15 @@ static int send_cancel(struct hci_dev *hdev, void *data)
mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_MESH_SEND_CANCEL,
0, NULL, 0);
mgmt_pending_free(cmd);
return 0;
}
static void send_cancel_destroy(struct hci_dev *hdev, void *data, int err)
{
mgmt_pending_free(data);
}
static int mesh_send_cancel(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
@@ -2462,7 +2466,8 @@ static int mesh_send_cancel(struct sock *sk, struct hci_dev *hdev,
if (!cmd)
err = -ENOMEM;
else
err = hci_cmd_sync_queue(hdev, send_cancel, cmd, NULL);
err = hci_cmd_sync_queue(hdev, send_cancel, cmd,
send_cancel_destroy);
if (err < 0) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_MESH_SEND_CANCEL,