]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-5.10/bluetooth-refactor-set_exp_feature-with-a-feature-ta.patch
6.1-stable patches
[thirdparty/kernel/stable-queue.git] / queue-5.10 / bluetooth-refactor-set_exp_feature-with-a-feature-ta.patch
CommitLineData
7f87a3cd
SL
1From 2530dd42cf909251594d1aa00c51ae026bf5926d Mon Sep 17 00:00:00 2001
2From: Sasha Levin <sashal@kernel.org>
3Date: Sun, 15 Aug 2021 20:17:15 +0800
4Subject: Bluetooth: refactor set_exp_feature with a feature table
5
6From: Joseph Hwang <josephsih@chromium.org>
7
8[ Upstream commit 93fb70bc112e922def6e50b37e20ccfce0c67c0a ]
9
10This patch refactors the set_exp_feature with a feature table
11consisting of UUIDs and the corresponding callback functions.
12In this way, a new experimental feature setting function can be
13simply added with its UUID and callback function.
14
15Signed-off-by: Joseph Hwang <josephsih@chromium.org>
16Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
17Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input")
18Signed-off-by: Sasha Levin <sashal@kernel.org>
19---
20 net/bluetooth/mgmt.c | 248 +++++++++++++++++++++++++------------------
21 1 file changed, 142 insertions(+), 106 deletions(-)
22
23diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
24index fd8bdafb71a0e..8acfd9db00d63 100644
25--- a/net/bluetooth/mgmt.c
26+++ b/net/bluetooth/mgmt.c
27@@ -3784,7 +3784,7 @@ static const u8 rpa_resolution_uuid[16] = {
28 static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
29 void *data, u16 data_len)
30 {
31- char buf[62]; /* Enough space for 3 features */
32+ char buf[62]; /* Enough space for 3 features */
33 struct mgmt_rp_read_exp_features_info *rp = (void *)buf;
34 u16 idx = 0;
35 u32 flags;
36@@ -3870,150 +3870,186 @@ static int exp_debug_feature_changed(bool enabled, struct sock *skip)
37 }
38 #endif
39
40-static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
41- void *data, u16 data_len)
42+#define EXP_FEAT(_uuid, _set_func) \
43+{ \
44+ .uuid = _uuid, \
45+ .set_func = _set_func, \
46+}
47+
48+/* The zero key uuid is special. Multiple exp features are set through it. */
49+static int set_zero_key_func(struct sock *sk, struct hci_dev *hdev,
50+ struct mgmt_cp_set_exp_feature *cp, u16 data_len)
51 {
52- struct mgmt_cp_set_exp_feature *cp = data;
53 struct mgmt_rp_set_exp_feature rp;
54
55- bt_dev_dbg(hdev, "sock %p", sk);
56-
57- if (!memcmp(cp->uuid, ZERO_KEY, 16)) {
58- memset(rp.uuid, 0, 16);
59- rp.flags = cpu_to_le32(0);
60+ memset(rp.uuid, 0, 16);
61+ rp.flags = cpu_to_le32(0);
62
63 #ifdef CONFIG_BT_FEATURE_DEBUG
64- if (!hdev) {
65- bool changed = bt_dbg_get();
66+ if (!hdev) {
67+ bool changed = bt_dbg_get();
68
69- bt_dbg_set(false);
70+ bt_dbg_set(false);
71
72- if (changed)
73- exp_debug_feature_changed(false, sk);
74- }
75+ if (changed)
76+ exp_debug_feature_changed(false, sk);
77+ }
78 #endif
79
80- if (hdev && use_ll_privacy(hdev) && !hdev_is_powered(hdev)) {
81- bool changed = hci_dev_test_flag(hdev,
82- HCI_ENABLE_LL_PRIVACY);
83+ if (hdev && use_ll_privacy(hdev) && !hdev_is_powered(hdev)) {
84+ bool changed = hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY);
85
86- hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
87+ hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
88
89- if (changed)
90- exp_ll_privacy_feature_changed(false, hdev, sk);
91- }
92+ if (changed)
93+ exp_ll_privacy_feature_changed(false, hdev, sk);
94+ }
95
96- hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
97+ hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
98
99- return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
100- MGMT_OP_SET_EXP_FEATURE, 0,
101- &rp, sizeof(rp));
102- }
103+ return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
104+ MGMT_OP_SET_EXP_FEATURE, 0,
105+ &rp, sizeof(rp));
106+}
107
108 #ifdef CONFIG_BT_FEATURE_DEBUG
109- if (!memcmp(cp->uuid, debug_uuid, 16)) {
110- bool val, changed;
111- int err;
112+static int set_debug_func(struct sock *sk, struct hci_dev *hdev,
113+ struct mgmt_cp_set_exp_feature *cp, u16 data_len)
114+{
115+ struct mgmt_rp_set_exp_feature rp;
116
117- /* Command requires to use the non-controller index */
118- if (hdev)
119- return mgmt_cmd_status(sk, hdev->id,
120- MGMT_OP_SET_EXP_FEATURE,
121- MGMT_STATUS_INVALID_INDEX);
122+ bool val, changed;
123+ int err;
124
125- /* Parameters are limited to a single octet */
126- if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
127- return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
128- MGMT_OP_SET_EXP_FEATURE,
129- MGMT_STATUS_INVALID_PARAMS);
130+ /* Command requires to use the non-controller index */
131+ if (hdev)
132+ return mgmt_cmd_status(sk, hdev->id,
133+ MGMT_OP_SET_EXP_FEATURE,
134+ MGMT_STATUS_INVALID_INDEX);
135
136- /* Only boolean on/off is supported */
137- if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
138- return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
139- MGMT_OP_SET_EXP_FEATURE,
140- MGMT_STATUS_INVALID_PARAMS);
141+ /* Parameters are limited to a single octet */
142+ if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
143+ return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
144+ MGMT_OP_SET_EXP_FEATURE,
145+ MGMT_STATUS_INVALID_PARAMS);
146
147- val = !!cp->param[0];
148- changed = val ? !bt_dbg_get() : bt_dbg_get();
149- bt_dbg_set(val);
150+ /* Only boolean on/off is supported */
151+ if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
152+ return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
153+ MGMT_OP_SET_EXP_FEATURE,
154+ MGMT_STATUS_INVALID_PARAMS);
155
156- memcpy(rp.uuid, debug_uuid, 16);
157- rp.flags = cpu_to_le32(val ? BIT(0) : 0);
158+ val = !!cp->param[0];
159+ changed = val ? !bt_dbg_get() : bt_dbg_get();
160+ bt_dbg_set(val);
161
162- hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
163+ memcpy(rp.uuid, debug_uuid, 16);
164+ rp.flags = cpu_to_le32(val ? BIT(0) : 0);
165
166- err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
167- MGMT_OP_SET_EXP_FEATURE, 0,
168- &rp, sizeof(rp));
169+ hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
170
171- if (changed)
172- exp_debug_feature_changed(val, sk);
173+ err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
174+ MGMT_OP_SET_EXP_FEATURE, 0,
175+ &rp, sizeof(rp));
176
177- return err;
178- }
179+ if (changed)
180+ exp_debug_feature_changed(val, sk);
181+
182+ return err;
183+}
184 #endif
185
186- if (!memcmp(cp->uuid, rpa_resolution_uuid, 16)) {
187- bool val, changed;
188- int err;
189- u32 flags;
190+static int set_rpa_resolution_func(struct sock *sk, struct hci_dev *hdev,
191+ struct mgmt_cp_set_exp_feature *cp,
192+ u16 data_len)
193+{
194+ struct mgmt_rp_set_exp_feature rp;
195+ bool val, changed;
196+ int err;
197+ u32 flags;
198+
199+ /* Command requires to use the controller index */
200+ if (!hdev)
201+ return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
202+ MGMT_OP_SET_EXP_FEATURE,
203+ MGMT_STATUS_INVALID_INDEX);
204
205- /* Command requires to use the controller index */
206- if (!hdev)
207- return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
208- MGMT_OP_SET_EXP_FEATURE,
209- MGMT_STATUS_INVALID_INDEX);
210+ /* Changes can only be made when controller is powered down */
211+ if (hdev_is_powered(hdev))
212+ return mgmt_cmd_status(sk, hdev->id,
213+ MGMT_OP_SET_EXP_FEATURE,
214+ MGMT_STATUS_REJECTED);
215
216- /* Changes can only be made when controller is powered down */
217- if (hdev_is_powered(hdev))
218- return mgmt_cmd_status(sk, hdev->id,
219- MGMT_OP_SET_EXP_FEATURE,
220- MGMT_STATUS_REJECTED);
221+ /* Parameters are limited to a single octet */
222+ if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
223+ return mgmt_cmd_status(sk, hdev->id,
224+ MGMT_OP_SET_EXP_FEATURE,
225+ MGMT_STATUS_INVALID_PARAMS);
226
227- /* Parameters are limited to a single octet */
228- if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
229- return mgmt_cmd_status(sk, hdev->id,
230- MGMT_OP_SET_EXP_FEATURE,
231- MGMT_STATUS_INVALID_PARAMS);
232+ /* Only boolean on/off is supported */
233+ if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
234+ return mgmt_cmd_status(sk, hdev->id,
235+ MGMT_OP_SET_EXP_FEATURE,
236+ MGMT_STATUS_INVALID_PARAMS);
237
238- /* Only boolean on/off is supported */
239- if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
240- return mgmt_cmd_status(sk, hdev->id,
241- MGMT_OP_SET_EXP_FEATURE,
242- MGMT_STATUS_INVALID_PARAMS);
243+ val = !!cp->param[0];
244
245- val = !!cp->param[0];
246+ if (val) {
247+ changed = !hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY);
248+ hci_dev_set_flag(hdev, HCI_ENABLE_LL_PRIVACY);
249+ hci_dev_clear_flag(hdev, HCI_ADVERTISING);
250
251- if (val) {
252- changed = !hci_dev_test_flag(hdev,
253- HCI_ENABLE_LL_PRIVACY);
254- hci_dev_set_flag(hdev, HCI_ENABLE_LL_PRIVACY);
255- hci_dev_clear_flag(hdev, HCI_ADVERTISING);
256+ /* Enable LL privacy + supported settings changed */
257+ flags = BIT(0) | BIT(1);
258+ } else {
259+ changed = hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY);
260+ hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
261
262- /* Enable LL privacy + supported settings changed */
263- flags = BIT(0) | BIT(1);
264- } else {
265- changed = hci_dev_test_flag(hdev,
266- HCI_ENABLE_LL_PRIVACY);
267- hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
268+ /* Disable LL privacy + supported settings changed */
269+ flags = BIT(1);
270+ }
271
272- /* Disable LL privacy + supported settings changed */
273- flags = BIT(1);
274- }
275+ memcpy(rp.uuid, rpa_resolution_uuid, 16);
276+ rp.flags = cpu_to_le32(flags);
277
278- memcpy(rp.uuid, rpa_resolution_uuid, 16);
279- rp.flags = cpu_to_le32(flags);
280+ hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
281
282- hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
283+ err = mgmt_cmd_complete(sk, hdev->id,
284+ MGMT_OP_SET_EXP_FEATURE, 0,
285+ &rp, sizeof(rp));
286
287- err = mgmt_cmd_complete(sk, hdev->id,
288- MGMT_OP_SET_EXP_FEATURE, 0,
289- &rp, sizeof(rp));
290+ if (changed)
291+ exp_ll_privacy_feature_changed(val, hdev, sk);
292
293- if (changed)
294- exp_ll_privacy_feature_changed(val, hdev, sk);
295+ return err;
296+}
297
298- return err;
299+static const struct mgmt_exp_feature {
300+ const u8 *uuid;
301+ int (*set_func)(struct sock *sk, struct hci_dev *hdev,
302+ struct mgmt_cp_set_exp_feature *cp, u16 data_len);
303+} exp_features[] = {
304+ EXP_FEAT(ZERO_KEY, set_zero_key_func),
305+#ifdef CONFIG_BT_FEATURE_DEBUG
306+ EXP_FEAT(debug_uuid, set_debug_func),
307+#endif
308+ EXP_FEAT(rpa_resolution_uuid, set_rpa_resolution_func),
309+
310+ /* end with a null feature */
311+ EXP_FEAT(NULL, NULL)
312+};
313+
314+static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
315+ void *data, u16 data_len)
316+{
317+ struct mgmt_cp_set_exp_feature *cp = data;
318+ size_t i = 0;
319+
320+ bt_dev_dbg(hdev, "sock %p", sk);
321+
322+ for (i = 0; exp_features[i].uuid; i++) {
323+ if (!memcmp(cp->uuid, exp_features[i].uuid, 16))
324+ return exp_features[i].set_func(sk, hdev, cp, data_len);
325 }
326
327 return mgmt_cmd_status(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
328--
3292.43.0
330