xref: /linux/drivers/hid/bpf/hid_bpf_dispatch.c (revision 4f7153cf461ed0f78d8da8c9fd02d38728a76b90)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 /*
4  *  HID-BPF support for Linux
5  *
6  *  Copyright (c) 2022 Benjamin Tissoires
7  */
8 
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 #include <linux/bitops.h>
11 #include <linux/btf.h>
12 #include <linux/btf_ids.h>
13 #include <linux/filter.h>
14 #include <linux/hid.h>
15 #include <linux/hid_bpf.h>
16 #include <linux/init.h>
17 #include <linux/kfifo.h>
18 #include <linux/module.h>
19 #include <linux/workqueue.h>
20 #include "hid_bpf_dispatch.h"
21 #include "entrypoints/entrypoints.lskel.h"
22 
23 struct hid_bpf_ops *hid_bpf_ops;
24 EXPORT_SYMBOL(hid_bpf_ops);
25 
26 /**
27  * hid_bpf_device_event - Called whenever an event is coming in from the device
28  *
29  * @ctx: The HID-BPF context
30  *
31  * @return %0 on success and keep processing; a positive value to change the
32  * incoming size buffer; a negative error code to interrupt the processing
33  * of this event
34  *
35  * Declare an %fmod_ret tracing bpf program to this function and attach this
36  * program through hid_bpf_attach_prog() to have this helper called for
37  * any incoming event from the device itself.
38  *
39  * The function is called while on IRQ context, so we can not sleep.
40  */
41 /* never used by the kernel but declared so we can load and attach a tracepoint */
42 __weak noinline int hid_bpf_device_event(struct hid_bpf_ctx *ctx)
43 {
44 	return 0;
45 }
46 ALLOW_ERROR_INJECTION(hid_bpf_device_event, ERRNO);
47 
48 u8 *
49 dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data,
50 			      u32 *size, int interrupt)
51 {
52 	struct hid_bpf_ctx_kern ctx_kern = {
53 		.ctx = {
54 			.hid = hdev,
55 			.report_type = type,
56 			.allocated_size = hdev->bpf.allocated_data,
57 			.size = *size,
58 		},
59 		.data = hdev->bpf.device_data,
60 	};
61 	int ret;
62 
63 	if (type >= HID_REPORT_TYPES)
64 		return ERR_PTR(-EINVAL);
65 
66 	/* no program has been attached yet */
67 	if (!hdev->bpf.device_data)
68 		return data;
69 
70 	memset(ctx_kern.data, 0, hdev->bpf.allocated_data);
71 	memcpy(ctx_kern.data, data, *size);
72 
73 	ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_DEVICE_EVENT, &ctx_kern);
74 	if (ret < 0)
75 		return ERR_PTR(ret);
76 
77 	if (ret) {
78 		if (ret > ctx_kern.ctx.allocated_size)
79 			return ERR_PTR(-EINVAL);
80 
81 		*size = ret;
82 	}
83 
84 	return ctx_kern.data;
85 }
86 EXPORT_SYMBOL_GPL(dispatch_hid_bpf_device_event);
87 
88 /**
89  * hid_bpf_get_data - Get the kernel memory pointer associated with the context @ctx
90  *
91  * @ctx: The HID-BPF context
92  * @offset: The offset within the memory
93  * @rdwr_buf_size: the const size of the buffer
94  *
95  * @returns %NULL on error, an %__u8 memory pointer on success
96  */
97 noinline __u8 *
98 hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr_buf_size)
99 {
100 	struct hid_bpf_ctx_kern *ctx_kern;
101 
102 	if (!ctx)
103 		return NULL;
104 
105 	ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
106 
107 	if (rdwr_buf_size + offset > ctx->allocated_size)
108 		return NULL;
109 
110 	return ctx_kern->data + offset;
111 }
112 
113 /*
114  * The following set contains all functions we agree BPF programs
115  * can use.
116  */
117 BTF_SET8_START(hid_bpf_kfunc_ids)
118 BTF_ID_FLAGS(func, call_hid_bpf_prog_put_deferred)
119 BTF_ID_FLAGS(func, hid_bpf_get_data, KF_RET_NULL)
120 BTF_SET8_END(hid_bpf_kfunc_ids)
121 
122 static const struct btf_kfunc_id_set hid_bpf_kfunc_set = {
123 	.owner = THIS_MODULE,
124 	.set   = &hid_bpf_kfunc_ids,
125 };
126 
127 static int device_match_id(struct device *dev, const void *id)
128 {
129 	struct hid_device *hdev = to_hid_device(dev);
130 
131 	return hdev->id == *(int *)id;
132 }
133 
134 static int __hid_bpf_allocate_data(struct hid_device *hdev, u8 **data, u32 *size)
135 {
136 	u8 *alloc_data;
137 	unsigned int i, j, max_report_len = 0;
138 	size_t alloc_size = 0;
139 
140 	/* compute the maximum report length for this device */
141 	for (i = 0; i < HID_REPORT_TYPES; i++) {
142 		struct hid_report_enum *report_enum = hdev->report_enum + i;
143 
144 		for (j = 0; j < HID_MAX_IDS; j++) {
145 			struct hid_report *report = report_enum->report_id_hash[j];
146 
147 			if (report)
148 				max_report_len = max(max_report_len, hid_report_len(report));
149 		}
150 	}
151 
152 	/*
153 	 * Give us a little bit of extra space and some predictability in the
154 	 * buffer length we create. This way, we can tell users that they can
155 	 * work on chunks of 64 bytes of memory without having the bpf verifier
156 	 * scream at them.
157 	 */
158 	alloc_size = DIV_ROUND_UP(max_report_len, 64) * 64;
159 
160 	alloc_data = kzalloc(alloc_size, GFP_KERNEL);
161 	if (!alloc_data)
162 		return -ENOMEM;
163 
164 	*data = alloc_data;
165 	*size = alloc_size;
166 
167 	return 0;
168 }
169 
170 static int hid_bpf_allocate_event_data(struct hid_device *hdev)
171 {
172 	/* hdev->bpf.device_data is already allocated, abort */
173 	if (hdev->bpf.device_data)
174 		return 0;
175 
176 	return __hid_bpf_allocate_data(hdev, &hdev->bpf.device_data, &hdev->bpf.allocated_data);
177 }
178 
179 /**
180  * hid_bpf_attach_prog - Attach the given @prog_fd to the given HID device
181  *
182  * @hid_id: the system unique identifier of the HID device
183  * @prog_fd: an fd in the user process representing the program to attach
184  * @flags: any logical OR combination of &enum hid_bpf_attach_flags
185  *
186  * @returns %0 on success, an error code otherwise.
187  */
188 /* called from syscall */
189 noinline int
190 hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
191 {
192 	struct hid_device *hdev;
193 	struct device *dev;
194 	int err, prog_type = hid_bpf_get_prog_attach_type(prog_fd);
195 
196 	if (!hid_bpf_ops)
197 		return -EINVAL;
198 
199 	if (prog_type < 0)
200 		return prog_type;
201 
202 	if (prog_type >= HID_BPF_PROG_TYPE_MAX)
203 		return -EINVAL;
204 
205 	if ((flags & ~HID_BPF_FLAG_MASK))
206 		return -EINVAL;
207 
208 	dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id);
209 	if (!dev)
210 		return -EINVAL;
211 
212 	hdev = to_hid_device(dev);
213 
214 	if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) {
215 		err = hid_bpf_allocate_event_data(hdev);
216 		if (err)
217 			return err;
218 	}
219 
220 	return __hid_bpf_attach_prog(hdev, prog_type, prog_fd, flags);
221 }
222 
223 /**
224  * hid_bpf_allocate_context - Allocate a context to the given HID device
225  *
226  * @hid_id: the system unique identifier of the HID device
227  *
228  * @returns A pointer to &struct hid_bpf_ctx on success, %NULL on error.
229  */
230 noinline struct hid_bpf_ctx *
231 hid_bpf_allocate_context(unsigned int hid_id)
232 {
233 	struct hid_device *hdev;
234 	struct hid_bpf_ctx_kern *ctx_kern = NULL;
235 	struct device *dev;
236 
237 	if (!hid_bpf_ops)
238 		return NULL;
239 
240 	dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id);
241 	if (!dev)
242 		return NULL;
243 
244 	hdev = to_hid_device(dev);
245 
246 	ctx_kern = kzalloc(sizeof(*ctx_kern), GFP_KERNEL);
247 	if (!ctx_kern)
248 		return NULL;
249 
250 	ctx_kern->ctx.hid = hdev;
251 
252 	return &ctx_kern->ctx;
253 }
254 
255 /**
256  * hid_bpf_release_context - Release the previously allocated context @ctx
257  *
258  * @ctx: the HID-BPF context to release
259  *
260  */
261 noinline void
262 hid_bpf_release_context(struct hid_bpf_ctx *ctx)
263 {
264 	struct hid_bpf_ctx_kern *ctx_kern;
265 
266 	if (!ctx)
267 		return;
268 
269 	ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
270 
271 	kfree(ctx_kern);
272 }
273 
274 /**
275  * hid_bpf_hw_request - Communicate with a HID device
276  *
277  * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
278  * @buf: a %PTR_TO_MEM buffer
279  * @buf__sz: the size of the data to transfer
280  * @rtype: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
281  * @reqtype: the type of the request (%HID_REQ_GET_REPORT, %HID_REQ_SET_REPORT, ...)
282  *
283  * @returns %0 on success, a negative error code otherwise.
284  */
285 noinline int
286 hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
287 		   enum hid_report_type rtype, enum hid_class_request reqtype)
288 {
289 	struct hid_device *hdev;
290 	struct hid_report *report;
291 	struct hid_report_enum *report_enum;
292 	u8 *dma_data;
293 	u32 report_len;
294 	int ret;
295 
296 	/* check arguments */
297 	if (!ctx || !hid_bpf_ops || !buf)
298 		return -EINVAL;
299 
300 	switch (rtype) {
301 	case HID_INPUT_REPORT:
302 	case HID_OUTPUT_REPORT:
303 	case HID_FEATURE_REPORT:
304 		break;
305 	default:
306 		return -EINVAL;
307 	}
308 
309 	switch (reqtype) {
310 	case HID_REQ_GET_REPORT:
311 	case HID_REQ_GET_IDLE:
312 	case HID_REQ_GET_PROTOCOL:
313 	case HID_REQ_SET_REPORT:
314 	case HID_REQ_SET_IDLE:
315 	case HID_REQ_SET_PROTOCOL:
316 		break;
317 	default:
318 		return -EINVAL;
319 	}
320 
321 	if (buf__sz < 1)
322 		return -EINVAL;
323 
324 	hdev = (struct hid_device *)ctx->hid; /* discard const */
325 
326 	report_enum = hdev->report_enum + rtype;
327 	report = hid_bpf_ops->hid_get_report(report_enum, buf);
328 	if (!report)
329 		return -EINVAL;
330 
331 	report_len = hid_report_len(report);
332 
333 	if (buf__sz > report_len)
334 		buf__sz = report_len;
335 
336 	dma_data = kmemdup(buf, buf__sz, GFP_KERNEL);
337 	if (!dma_data)
338 		return -ENOMEM;
339 
340 	ret = hid_bpf_ops->hid_hw_raw_request(hdev,
341 					      dma_data[0],
342 					      dma_data,
343 					      buf__sz,
344 					      rtype,
345 					      reqtype);
346 
347 	if (ret > 0)
348 		memcpy(buf, dma_data, ret);
349 
350 	kfree(dma_data);
351 	return ret;
352 }
353 
354 /* for syscall HID-BPF */
355 BTF_SET8_START(hid_bpf_syscall_kfunc_ids)
356 BTF_ID_FLAGS(func, hid_bpf_attach_prog)
357 BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL)
358 BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE)
359 BTF_ID_FLAGS(func, hid_bpf_hw_request)
360 BTF_SET8_END(hid_bpf_syscall_kfunc_ids)
361 
362 static const struct btf_kfunc_id_set hid_bpf_syscall_kfunc_set = {
363 	.owner = THIS_MODULE,
364 	.set   = &hid_bpf_syscall_kfunc_ids,
365 };
366 
367 int hid_bpf_connect_device(struct hid_device *hdev)
368 {
369 	struct hid_bpf_prog_list *prog_list;
370 
371 	rcu_read_lock();
372 	prog_list = rcu_dereference(hdev->bpf.progs[HID_BPF_PROG_TYPE_DEVICE_EVENT]);
373 	rcu_read_unlock();
374 
375 	/* only allocate BPF data if there are programs attached */
376 	if (!prog_list)
377 		return 0;
378 
379 	return hid_bpf_allocate_event_data(hdev);
380 }
381 EXPORT_SYMBOL_GPL(hid_bpf_connect_device);
382 
383 void hid_bpf_disconnect_device(struct hid_device *hdev)
384 {
385 	kfree(hdev->bpf.device_data);
386 	hdev->bpf.device_data = NULL;
387 	hdev->bpf.allocated_data = 0;
388 }
389 EXPORT_SYMBOL_GPL(hid_bpf_disconnect_device);
390 
391 void hid_bpf_destroy_device(struct hid_device *hdev)
392 {
393 	if (!hdev)
394 		return;
395 
396 	/* mark the device as destroyed in bpf so we don't reattach it */
397 	hdev->bpf.destroyed = true;
398 
399 	__hid_bpf_destroy_device(hdev);
400 }
401 EXPORT_SYMBOL_GPL(hid_bpf_destroy_device);
402 
403 void hid_bpf_device_init(struct hid_device *hdev)
404 {
405 	spin_lock_init(&hdev->bpf.progs_lock);
406 }
407 EXPORT_SYMBOL_GPL(hid_bpf_device_init);
408 
409 static int __init hid_bpf_init(void)
410 {
411 	int err;
412 
413 	/* Note: if we exit with an error any time here, we would entirely break HID, which
414 	 * is probably not something we want. So we log an error and return success.
415 	 *
416 	 * This is not a big deal: the syscall allowing to attach a BPF program to a HID device
417 	 * will not be available, so nobody will be able to use the functionality.
418 	 */
419 
420 	err = register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &hid_bpf_kfunc_set);
421 	if (err) {
422 		pr_warn("error while setting HID BPF tracing kfuncs: %d", err);
423 		return 0;
424 	}
425 
426 	err = hid_bpf_preload_skel();
427 	if (err) {
428 		pr_warn("error while preloading HID BPF dispatcher: %d", err);
429 		return 0;
430 	}
431 
432 	/* register syscalls after we are sure we can load our preloaded bpf program */
433 	err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set);
434 	if (err) {
435 		pr_warn("error while setting HID BPF syscall kfuncs: %d", err);
436 		return 0;
437 	}
438 
439 	return 0;
440 }
441 
442 static void __exit hid_bpf_exit(void)
443 {
444 	/* HID depends on us, so if we hit that code, we are guaranteed that hid
445 	 * has been removed and thus we do not need to clear the HID devices
446 	 */
447 	hid_bpf_free_links_and_skel();
448 }
449 
450 late_initcall(hid_bpf_init);
451 module_exit(hid_bpf_exit);
452 MODULE_AUTHOR("Benjamin Tissoires");
453 MODULE_LICENSE("GPL");
454