diff options
author | Jaganath Kanakkassery <jaganath.k@samsung.com> | 2014-12-11 01:13:12 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-12-11 08:08:47 -0500 |
commit | 3ad675827f4a3623b7fc51ffe8fdb0347b3cbc53 (patch) | |
tree | f8952e7de7fc3ea48ae2f633059a441bc2dc55df /net | |
parent | 134d3b3550f050b9bec37111824452064d1ed928 (diff) |
Bluetooth: Fix missing hci_dev_lock/unlock in mgmt req_complete()
mgmt_pending_remove() should be called with hci_dev_lock protection
and currently the rule to take dev lock is that all mgmt req_complete
functions should take dev lock. So this patch fixes the same in the
missing functions
Without this patch there is a chance of invalid memory access while
accessing the mgmt_pending list like below
bluetoothd: 392] [0] Backtrace:
bluetoothd: 392] [0] [<c04ec770>] (pending_eir_or_class+0x0/0x68) from [<c04f1830>] (add_uuid+0x34/0x1c4)
bluetoothd: 392] [0] [<c04f17fc>] (add_uuid+0x0/0x1c4) from [<c04f3cc4>] (mgmt_control+0x204/0x274)
bluetoothd: 392] [0] [<c04f3ac0>] (mgmt_control+0x0/0x274) from [<c04f609c>] (hci_sock_sendmsg+0x80/0x308)
bluetoothd: 392] [0] [<c04f601c>] (hci_sock_sendmsg+0x0/0x308) from [<c03d4d68>] (sock_aio_write+0x144/0x174)
bluetoothd: 392] [0] r8:00000000 r7 7c1be90 r6 7c1be18 r5:00000017 r4 a90ea80
bluetoothd: 392] [0] [<c03d4c24>] (sock_aio_write+0x0/0x174) from [<c00e2d4c>] (do_sync_write+0xb0/0xe0)
bluetoothd: 392] [0] [<c00e2c9c>] (do_sync_write+0x0/0xe0) from [<c00e371c>] (vfs_write+0x134/0x13c)
bluetoothd: 392] [0] r8:00000000 r7 7c1bf70 r6:beeca5c8 r5:00000017 r4 7c05900
bluetoothd: 392] [0] [<c00e35e8>] (vfs_write+0x0/0x13c) from [<c00e3910>] (sys_write+0x44/0x70)
bluetoothd: 392] [0] r8:00000000 r7:00000004 r6:00000017 r5:beeca5c8 r4 7c05900
bluetoothd: 392] [0] [<c00e38cc>] (sys_write+0x0/0x70) from [<c000e3c0>] (ret_fast_syscall+0x0/0x30)
bluetoothd: 392] [0] r9 7c1a000 r8:c000e568 r6:400b5f10 r5:403896d8 r4:beeca604
bluetoothd: 392] [0] Code: e28cc00c e152000c 0a00000f e3a00001 (e1d210b8)
bluetoothd: 392] [0] ---[ end trace 67b6ac67435864c4 ]---
bluetoothd: 392] [0] Kernel panic - not syncing: Fatal exception
Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/hci_core.c | 2 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 18 |
2 files changed, 14 insertions, 6 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 96e7321c57a4..ecd7c01317bc 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -3083,7 +3083,9 @@ static void hci_power_on(struct work_struct *work) | |||
3083 | 3083 | ||
3084 | err = hci_dev_do_open(hdev); | 3084 | err = hci_dev_do_open(hdev); |
3085 | if (err < 0) { | 3085 | if (err < 0) { |
3086 | hci_dev_lock(hdev); | ||
3086 | mgmt_set_powered_failed(hdev, err); | 3087 | mgmt_set_powered_failed(hdev, err); |
3088 | hci_dev_unlock(hdev); | ||
3087 | return; | 3089 | return; |
3088 | } | 3090 | } |
3089 | 3091 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 44b20deb6038..16ac03730f4d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -2199,12 +2199,14 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status) | |||
2199 | { | 2199 | { |
2200 | struct cmd_lookup match = { NULL, hdev }; | 2200 | struct cmd_lookup match = { NULL, hdev }; |
2201 | 2201 | ||
2202 | hci_dev_lock(hdev); | ||
2203 | |||
2202 | if (status) { | 2204 | if (status) { |
2203 | u8 mgmt_err = mgmt_status(status); | 2205 | u8 mgmt_err = mgmt_status(status); |
2204 | 2206 | ||
2205 | mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp, | 2207 | mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp, |
2206 | &mgmt_err); | 2208 | &mgmt_err); |
2207 | return; | 2209 | goto unlock; |
2208 | } | 2210 | } |
2209 | 2211 | ||
2210 | mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match); | 2212 | mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match); |
@@ -2222,17 +2224,16 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status) | |||
2222 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | 2224 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { |
2223 | struct hci_request req; | 2225 | struct hci_request req; |
2224 | 2226 | ||
2225 | hci_dev_lock(hdev); | ||
2226 | |||
2227 | hci_req_init(&req, hdev); | 2227 | hci_req_init(&req, hdev); |
2228 | update_adv_data(&req); | 2228 | update_adv_data(&req); |
2229 | update_scan_rsp_data(&req); | 2229 | update_scan_rsp_data(&req); |
2230 | hci_req_run(&req, NULL); | 2230 | hci_req_run(&req, NULL); |
2231 | 2231 | ||
2232 | hci_update_background_scan(hdev); | 2232 | hci_update_background_scan(hdev); |
2233 | |||
2234 | hci_dev_unlock(hdev); | ||
2235 | } | 2233 | } |
2234 | |||
2235 | unlock: | ||
2236 | hci_dev_unlock(hdev); | ||
2236 | } | 2237 | } |
2237 | 2238 | ||
2238 | static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | 2239 | static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) |
@@ -4279,12 +4280,14 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status) | |||
4279 | { | 4280 | { |
4280 | struct cmd_lookup match = { NULL, hdev }; | 4281 | struct cmd_lookup match = { NULL, hdev }; |
4281 | 4282 | ||
4283 | hci_dev_lock(hdev); | ||
4284 | |||
4282 | if (status) { | 4285 | if (status) { |
4283 | u8 mgmt_err = mgmt_status(status); | 4286 | u8 mgmt_err = mgmt_status(status); |
4284 | 4287 | ||
4285 | mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, | 4288 | mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, |
4286 | cmd_status_rsp, &mgmt_err); | 4289 | cmd_status_rsp, &mgmt_err); |
4287 | return; | 4290 | goto unlock; |
4288 | } | 4291 | } |
4289 | 4292 | ||
4290 | if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) | 4293 | if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) |
@@ -4299,6 +4302,9 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status) | |||
4299 | 4302 | ||
4300 | if (match.sk) | 4303 | if (match.sk) |
4301 | sock_put(match.sk); | 4304 | sock_put(match.sk); |
4305 | |||
4306 | unlock: | ||
4307 | hci_dev_unlock(hdev); | ||
4302 | } | 4308 | } |
4303 | 4309 | ||
4304 | static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, | 4310 | static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, |