diff options
author | Jaganath Kanakkassery <jaganath.k.os@gmail.com> | 2017-10-25 01:28:48 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2017-10-29 09:07:10 -0400 |
commit | f17d858ed0a48270db4368d8cf370e3839ee6f4f (patch) | |
tree | 975b67fd9b1bf35c27320b25f11b8fa508d69a12 | |
parent | 858ff38af77fc660092e82474ecc6ac135ed29fe (diff) |
Bluetooth: Fix potential memory leak
If command is added to req then it should be freed in case if
hdev is down or HCI_ADVERTISING flag is set.
This introduces a helper in hci_request to purge the cmd_q
to make cmd_q internal to hci_request which is used to fix
the leak.
This also replace accessing of cmd_q in hci_conn with the
new helper.
Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r-- | net/bluetooth/hci_conn.c | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_request.c | 5 | ||||
-rw-r--r-- | net/bluetooth/hci_request.h | 1 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 1 |
4 files changed, 8 insertions, 1 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index dc59eae54717..746adcb62259 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -907,7 +907,7 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | |||
907 | */ | 907 | */ |
908 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN) && | 908 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN) && |
909 | hdev->le_scan_type == LE_SCAN_ACTIVE) { | 909 | hdev->le_scan_type == LE_SCAN_ACTIVE) { |
910 | skb_queue_purge(&req.cmd_q); | 910 | hci_req_purge(&req); |
911 | hci_conn_del(conn); | 911 | hci_conn_del(conn); |
912 | return ERR_PTR(-EBUSY); | 912 | return ERR_PTR(-EBUSY); |
913 | } | 913 | } |
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index b73ac149de34..7f28d17dc792 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c | |||
@@ -41,6 +41,11 @@ void hci_req_init(struct hci_request *req, struct hci_dev *hdev) | |||
41 | req->err = 0; | 41 | req->err = 0; |
42 | } | 42 | } |
43 | 43 | ||
44 | void hci_req_purge(struct hci_request *req) | ||
45 | { | ||
46 | skb_queue_purge(&req->cmd_q); | ||
47 | } | ||
48 | |||
44 | static int req_run(struct hci_request *req, hci_req_complete_t complete, | 49 | static int req_run(struct hci_request *req, hci_req_complete_t complete, |
45 | hci_req_complete_skb_t complete_skb) | 50 | hci_req_complete_skb_t complete_skb) |
46 | { | 51 | { |
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h index dde77bd59f91..702beb140d9f 100644 --- a/net/bluetooth/hci_request.h +++ b/net/bluetooth/hci_request.h | |||
@@ -36,6 +36,7 @@ struct hci_request { | |||
36 | }; | 36 | }; |
37 | 37 | ||
38 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev); | 38 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev); |
39 | void hci_req_purge(struct hci_request *req); | ||
39 | int hci_req_run(struct hci_request *req, hci_req_complete_t complete); | 40 | int hci_req_run(struct hci_request *req, hci_req_complete_t complete); |
40 | int hci_req_run_skb(struct hci_request *req, hci_req_complete_skb_t complete); | 41 | int hci_req_run_skb(struct hci_request *req, hci_req_complete_skb_t complete); |
41 | void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, | 42 | void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 1fba2a03f8ae..07a3cc29f426 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -6383,6 +6383,7 @@ static int remove_advertising(struct sock *sk, struct hci_dev *hdev, | |||
6383 | if (skb_queue_empty(&req.cmd_q) || | 6383 | if (skb_queue_empty(&req.cmd_q) || |
6384 | !hdev_is_powered(hdev) || | 6384 | !hdev_is_powered(hdev) || |
6385 | hci_dev_test_flag(hdev, HCI_ADVERTISING)) { | 6385 | hci_dev_test_flag(hdev, HCI_ADVERTISING)) { |
6386 | hci_req_purge(&req); | ||
6386 | rp.instance = cp->instance; | 6387 | rp.instance = cp->instance; |
6387 | err = mgmt_cmd_complete(sk, hdev->id, | 6388 | err = mgmt_cmd_complete(sk, hdev->id, |
6388 | MGMT_OP_REMOVE_ADVERTISING, | 6389 | MGMT_OP_REMOVE_ADVERTISING, |