1 |
From d25b0186968b095d198cf0eaf1d9c48cd7fbbf20 Mon Sep 17 00:00:00 2001 |
2 |
From: Balakrishna Godavarthi <bgodavar@codeaurora.org> |
3 |
Date: Wed, 22 Aug 2018 17:50:05 +0530 |
4 |
Subject: [PATCH 046/145] Bluetooth: hci_qca: Remove hdev dereference in |
5 |
qca_close(). |
6 |
|
7 |
[ Upstream commit c2d7827338618a9e73a3f892ca63d9082bb7a94d ] |
8 |
|
9 |
When flag KASAN is set, we are seeing an following crash while removing |
10 |
hci_uart module. |
11 |
|
12 |
[ 50.589909] Unable to handle kernel paging request at virtual address 6b6b6b6b6b6b73 |
13 |
[ 50.597902] Mem abort info: |
14 |
[ 50.600846] Exception class = DABT (current EL), IL = 32 bits |
15 |
[ 50.606959] SET = 0, FnV = 0 |
16 |
[ 50.610142] EA = 0, S1PTW = 0 |
17 |
[ 50.613396] Data abort info: |
18 |
[ 50.616401] ISV = 0, ISS = 0x00000004 |
19 |
[ 50.620373] CM = 0, WnR = 0 |
20 |
[ 50.623466] [006b6b6b6b6b6b73] address between user and kernel address ranges |
21 |
[ 50.630818] Internal error: Oops: 96000004 [#1] PREEMPT SMP |
22 |
|
23 |
[ 50.671670] PC is at qca_power_shutdown+0x28/0x100 [hci_uart] |
24 |
[ 50.677593] LR is at qca_close+0x74/0xb0 [hci_uart] |
25 |
[ 50.775689] Process rmmod (pid: 2144, stack limit = 0xffffff801ba90000) |
26 |
[ 50.782493] Call trace: |
27 |
|
28 |
[ 50.872150] [<ffffff8000c3c81c>] qca_power_shutdown+0x28/0x100 [hci_uart] |
29 |
[ 50.879138] [<ffffff8000c3c968>] qca_close+0x74/0xb0 [hci_uart] |
30 |
[ 50.885238] [<ffffff8000c3a71c>] hci_uart_unregister_device+0x44/0x50 [hci_uart] |
31 |
[ 50.892846] [<ffffff8000c3c9f4>] qca_serdev_remove+0x50/0x5c [hci_uart] |
32 |
[ 50.899654] [<ffffff800844f630>] serdev_drv_remove+0x28/0x38 |
33 |
[ 50.905489] [<ffffff800850fc44>] device_release_driver_internal+0x140/0x1e4 |
34 |
[ 50.912653] [<ffffff800850fd94>] driver_detach+0x78/0x84 |
35 |
[ 50.918121] [<ffffff800850edac>] bus_remove_driver+0x80/0xa8 |
36 |
[ 50.923942] [<ffffff80085107dc>] driver_unregister+0x4c/0x58 |
37 |
[ 50.929768] [<ffffff8000c3ca8c>] qca_deinit+0x24/0x598 [hci_uart] |
38 |
[ 50.936045] [<ffffff8000c3ca10>] hci_uart_exit+0x10/0x48 [hci_uart] |
39 |
[ 50.942495] [<ffffff8008136630>] SyS_delete_module+0x17c/0x224 |
40 |
|
41 |
This crash is due to dereference of hdev, after freeing it. |
42 |
|
43 |
Signed-off-by: Balakrishna Godavarthi <bgodavar@codeaurora.org> |
44 |
Signed-off-by: Marcel Holtmann <marcel@holtmann.org> |
45 |
Signed-off-by: Sasha Levin <sashal@kernel.org> |
46 |
--- |
47 |
drivers/bluetooth/hci_qca.c | 15 +++++++++------ |
48 |
1 file changed, 9 insertions(+), 6 deletions(-) |
49 |
|
50 |
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c |
51 |
index 2fee65886d50..f0d593c3fa72 100644 |
52 |
--- a/drivers/bluetooth/hci_qca.c |
53 |
+++ b/drivers/bluetooth/hci_qca.c |
54 |
@@ -167,7 +167,7 @@ struct qca_serdev { |
55 |
}; |
56 |
|
57 |
static int qca_power_setup(struct hci_uart *hu, bool on); |
58 |
-static void qca_power_shutdown(struct hci_dev *hdev); |
59 |
+static void qca_power_shutdown(struct hci_uart *hu); |
60 |
|
61 |
static void __serial_clock_on(struct tty_struct *tty) |
62 |
{ |
63 |
@@ -609,7 +609,7 @@ static int qca_close(struct hci_uart *hu) |
64 |
if (hu->serdev) { |
65 |
qcadev = serdev_device_get_drvdata(hu->serdev); |
66 |
if (qcadev->btsoc_type == QCA_WCN3990) |
67 |
- qca_power_shutdown(hu->hdev); |
68 |
+ qca_power_shutdown(hu); |
69 |
else |
70 |
gpiod_set_value_cansleep(qcadev->bt_en, 0); |
71 |
|
72 |
@@ -1232,12 +1232,15 @@ static const struct qca_vreg_data qca_soc_data = { |
73 |
.num_vregs = 4, |
74 |
}; |
75 |
|
76 |
-static void qca_power_shutdown(struct hci_dev *hdev) |
77 |
+static void qca_power_shutdown(struct hci_uart *hu) |
78 |
{ |
79 |
- struct hci_uart *hu = hci_get_drvdata(hdev); |
80 |
+ struct serdev_device *serdev = hu->serdev; |
81 |
+ unsigned char cmd = QCA_WCN3990_POWEROFF_PULSE; |
82 |
|
83 |
host_set_baudrate(hu, 2400); |
84 |
- qca_send_power_pulse(hdev, QCA_WCN3990_POWEROFF_PULSE); |
85 |
+ hci_uart_set_flow_control(hu, true); |
86 |
+ serdev_device_write_buf(serdev, &cmd, sizeof(cmd)); |
87 |
+ hci_uart_set_flow_control(hu, false); |
88 |
qca_power_setup(hu, false); |
89 |
} |
90 |
|
91 |
@@ -1413,7 +1416,7 @@ static void qca_serdev_remove(struct serdev_device *serdev) |
92 |
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev); |
93 |
|
94 |
if (qcadev->btsoc_type == QCA_WCN3990) |
95 |
- qca_power_shutdown(qcadev->serdev_hu.hdev); |
96 |
+ qca_power_shutdown(&qcadev->serdev_hu); |
97 |
else |
98 |
clk_disable_unprepare(qcadev->susclk); |
99 |
|
100 |
-- |
101 |
2.19.1 |
102 |
|