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/minmax.h>
19 #include <linux/module.h>
20 #include <linux/workqueue.h>
21 #include "hid_bpf_dispatch.h"
22 #include "entrypoints/entrypoints.lskel.h"
23
24 struct hid_bpf_ops *hid_bpf_ops;
25 EXPORT_SYMBOL(hid_bpf_ops);
26
27 /**
28 * hid_bpf_device_event - Called whenever an event is coming in from the device
29 *
30 * @ctx: The HID-BPF context
31 *
32 * @return %0 on success and keep processing; a positive value to change the
33 * incoming size buffer; a negative error code to interrupt the processing
34 * of this event
35 *
36 * Declare an %fmod_ret tracing bpf program to this function and attach this
37 * program through hid_bpf_attach_prog() to have this helper called for
38 * any incoming event from the device itself.
39 *
40 * The function is called while on IRQ context, so we can not sleep.
41 */
42 /* never used by the kernel but declared so we can load and attach a tracepoint */
hid_bpf_device_event(struct hid_bpf_ctx * ctx)43 __weak noinline int hid_bpf_device_event(struct hid_bpf_ctx *ctx)
44 {
45 return 0;
46 }
47
48 u8 *
dispatch_hid_bpf_device_event(struct hid_device * hdev,enum hid_report_type type,u8 * data,u32 * size,int interrupt)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_rdesc_fixup - Called when the probe function parses the report
90 * descriptor of the HID device
91 *
92 * @ctx: The HID-BPF context
93 *
94 * @return 0 on success and keep processing; a positive value to change the
95 * incoming size buffer; a negative error code to interrupt the processing
96 * of this event
97 *
98 * Declare an %fmod_ret tracing bpf program to this function and attach this
99 * program through hid_bpf_attach_prog() to have this helper called before any
100 * parsing of the report descriptor by HID.
101 */
102 /* never used by the kernel but declared so we can load and attach a tracepoint */
hid_bpf_rdesc_fixup(struct hid_bpf_ctx * ctx)103 __weak noinline int hid_bpf_rdesc_fixup(struct hid_bpf_ctx *ctx)
104 {
105 return 0;
106 }
107
call_hid_bpf_rdesc_fixup(struct hid_device * hdev,u8 * rdesc,unsigned int * size)108 u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size)
109 {
110 int ret;
111 struct hid_bpf_ctx_kern ctx_kern = {
112 .ctx = {
113 .hid = hdev,
114 .size = *size,
115 .allocated_size = HID_MAX_DESCRIPTOR_SIZE,
116 },
117 };
118
119 ctx_kern.data = kzalloc(ctx_kern.ctx.allocated_size, GFP_KERNEL);
120 if (!ctx_kern.data)
121 goto ignore_bpf;
122
123 memcpy(ctx_kern.data, rdesc, min_t(unsigned int, *size, HID_MAX_DESCRIPTOR_SIZE));
124
125 ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_RDESC_FIXUP, &ctx_kern);
126 if (ret < 0)
127 goto ignore_bpf;
128
129 if (ret) {
130 if (ret > ctx_kern.ctx.allocated_size)
131 goto ignore_bpf;
132
133 *size = ret;
134 }
135
136 rdesc = krealloc(ctx_kern.data, *size, GFP_KERNEL);
137
138 return rdesc;
139
140 ignore_bpf:
141 kfree(ctx_kern.data);
142 return kmemdup(rdesc, *size, GFP_KERNEL);
143 }
144 EXPORT_SYMBOL_GPL(call_hid_bpf_rdesc_fixup);
145
146 /**
147 * hid_bpf_get_data - Get the kernel memory pointer associated with the context @ctx
148 *
149 * @ctx: The HID-BPF context
150 * @offset: The offset within the memory
151 * @rdwr_buf_size: the const size of the buffer
152 *
153 * @returns %NULL on error, an %__u8 memory pointer on success
154 */
155 noinline __u8 *
hid_bpf_get_data(struct hid_bpf_ctx * ctx,unsigned int offset,const size_t rdwr_buf_size)156 hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr_buf_size)
157 {
158 struct hid_bpf_ctx_kern *ctx_kern;
159
160 if (!ctx)
161 return NULL;
162
163 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
164
165 if (rdwr_buf_size + offset > ctx->allocated_size)
166 return NULL;
167
168 return ctx_kern->data + offset;
169 }
170
171 /*
172 * The following set contains all functions we agree BPF programs
173 * can use.
174 */
175 BTF_SET8_START(hid_bpf_kfunc_ids)
176 BTF_ID_FLAGS(func, hid_bpf_get_data, KF_RET_NULL)
177 BTF_SET8_END(hid_bpf_kfunc_ids)
178
179 static const struct btf_kfunc_id_set hid_bpf_kfunc_set = {
180 .owner = THIS_MODULE,
181 .set = &hid_bpf_kfunc_ids,
182 };
183
device_match_id(struct device * dev,const void * id)184 static int device_match_id(struct device *dev, const void *id)
185 {
186 struct hid_device *hdev = to_hid_device(dev);
187
188 return hdev->id == *(int *)id;
189 }
190
__hid_bpf_allocate_data(struct hid_device * hdev,u8 ** data,u32 * size)191 static int __hid_bpf_allocate_data(struct hid_device *hdev, u8 **data, u32 *size)
192 {
193 u8 *alloc_data;
194 unsigned int i, j, max_report_len = 0;
195 size_t alloc_size = 0;
196
197 /* compute the maximum report length for this device */
198 for (i = 0; i < HID_REPORT_TYPES; i++) {
199 struct hid_report_enum *report_enum = hdev->report_enum + i;
200
201 for (j = 0; j < HID_MAX_IDS; j++) {
202 struct hid_report *report = report_enum->report_id_hash[j];
203
204 if (report)
205 max_report_len = max(max_report_len, hid_report_len(report));
206 }
207 }
208
209 /*
210 * Give us a little bit of extra space and some predictability in the
211 * buffer length we create. This way, we can tell users that they can
212 * work on chunks of 64 bytes of memory without having the bpf verifier
213 * scream at them.
214 */
215 alloc_size = DIV_ROUND_UP(max_report_len, 64) * 64;
216
217 alloc_data = kzalloc(alloc_size, GFP_KERNEL);
218 if (!alloc_data)
219 return -ENOMEM;
220
221 *data = alloc_data;
222 *size = alloc_size;
223
224 return 0;
225 }
226
hid_bpf_allocate_event_data(struct hid_device * hdev)227 static int hid_bpf_allocate_event_data(struct hid_device *hdev)
228 {
229 /* hdev->bpf.device_data is already allocated, abort */
230 if (hdev->bpf.device_data)
231 return 0;
232
233 return __hid_bpf_allocate_data(hdev, &hdev->bpf.device_data, &hdev->bpf.allocated_data);
234 }
235
hid_bpf_reconnect(struct hid_device * hdev)236 int hid_bpf_reconnect(struct hid_device *hdev)
237 {
238 if (!test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status))
239 return device_reprobe(&hdev->dev);
240
241 return 0;
242 }
243
244 /**
245 * hid_bpf_attach_prog - Attach the given @prog_fd to the given HID device
246 *
247 * @hid_id: the system unique identifier of the HID device
248 * @prog_fd: an fd in the user process representing the program to attach
249 * @flags: any logical OR combination of &enum hid_bpf_attach_flags
250 *
251 * @returns an fd of a bpf_link object on success (> %0), an error code otherwise.
252 * Closing this fd will detach the program from the HID device (unless the bpf_link
253 * is pinned to the BPF file system).
254 */
255 /* called from syscall */
256 noinline int
hid_bpf_attach_prog(unsigned int hid_id,int prog_fd,__u32 flags)257 hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
258 {
259 struct hid_device *hdev;
260 struct device *dev;
261 int fd, err, prog_type = hid_bpf_get_prog_attach_type(prog_fd);
262
263 if (!hid_bpf_ops)
264 return -EINVAL;
265
266 if (prog_type < 0)
267 return prog_type;
268
269 if (prog_type >= HID_BPF_PROG_TYPE_MAX)
270 return -EINVAL;
271
272 if ((flags & ~HID_BPF_FLAG_MASK))
273 return -EINVAL;
274
275 dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id);
276 if (!dev)
277 return -EINVAL;
278
279 hdev = to_hid_device(dev);
280
281 if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) {
282 err = hid_bpf_allocate_event_data(hdev);
283 if (err)
284 return err;
285 }
286
287 fd = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, flags);
288 if (fd < 0)
289 return fd;
290
291 if (prog_type == HID_BPF_PROG_TYPE_RDESC_FIXUP) {
292 err = hid_bpf_reconnect(hdev);
293 if (err) {
294 close_fd(fd);
295 return err;
296 }
297 }
298
299 return fd;
300 }
301
302 /**
303 * hid_bpf_allocate_context - Allocate a context to the given HID device
304 *
305 * @hid_id: the system unique identifier of the HID device
306 *
307 * @returns A pointer to &struct hid_bpf_ctx on success, %NULL on error.
308 */
309 noinline struct hid_bpf_ctx *
hid_bpf_allocate_context(unsigned int hid_id)310 hid_bpf_allocate_context(unsigned int hid_id)
311 {
312 struct hid_device *hdev;
313 struct hid_bpf_ctx_kern *ctx_kern = NULL;
314 struct device *dev;
315
316 if (!hid_bpf_ops)
317 return NULL;
318
319 dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id);
320 if (!dev)
321 return NULL;
322
323 hdev = to_hid_device(dev);
324
325 ctx_kern = kzalloc(sizeof(*ctx_kern), GFP_KERNEL);
326 if (!ctx_kern)
327 return NULL;
328
329 ctx_kern->ctx.hid = hdev;
330
331 return &ctx_kern->ctx;
332 }
333
334 /**
335 * hid_bpf_release_context - Release the previously allocated context @ctx
336 *
337 * @ctx: the HID-BPF context to release
338 *
339 */
340 noinline void
hid_bpf_release_context(struct hid_bpf_ctx * ctx)341 hid_bpf_release_context(struct hid_bpf_ctx *ctx)
342 {
343 struct hid_bpf_ctx_kern *ctx_kern;
344
345 if (!ctx)
346 return;
347
348 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
349
350 kfree(ctx_kern);
351 }
352
353 /**
354 * hid_bpf_hw_request - Communicate with a HID device
355 *
356 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
357 * @buf: a %PTR_TO_MEM buffer
358 * @buf__sz: the size of the data to transfer
359 * @rtype: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
360 * @reqtype: the type of the request (%HID_REQ_GET_REPORT, %HID_REQ_SET_REPORT, ...)
361 *
362 * @returns %0 on success, a negative error code otherwise.
363 */
364 noinline int
hid_bpf_hw_request(struct hid_bpf_ctx * ctx,__u8 * buf,size_t buf__sz,enum hid_report_type rtype,enum hid_class_request reqtype)365 hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
366 enum hid_report_type rtype, enum hid_class_request reqtype)
367 {
368 struct hid_device *hdev;
369 struct hid_report *report;
370 struct hid_report_enum *report_enum;
371 u8 *dma_data;
372 u32 report_len;
373 int ret;
374
375 /* check arguments */
376 if (!ctx || !hid_bpf_ops || !buf)
377 return -EINVAL;
378
379 switch (rtype) {
380 case HID_INPUT_REPORT:
381 case HID_OUTPUT_REPORT:
382 case HID_FEATURE_REPORT:
383 break;
384 default:
385 return -EINVAL;
386 }
387
388 switch (reqtype) {
389 case HID_REQ_GET_REPORT:
390 case HID_REQ_GET_IDLE:
391 case HID_REQ_GET_PROTOCOL:
392 case HID_REQ_SET_REPORT:
393 case HID_REQ_SET_IDLE:
394 case HID_REQ_SET_PROTOCOL:
395 break;
396 default:
397 return -EINVAL;
398 }
399
400 if (buf__sz < 1)
401 return -EINVAL;
402
403 hdev = (struct hid_device *)ctx->hid; /* discard const */
404
405 report_enum = hdev->report_enum + rtype;
406 report = hid_bpf_ops->hid_get_report(report_enum, buf);
407 if (!report)
408 return -EINVAL;
409
410 report_len = hid_report_len(report);
411
412 if (buf__sz > report_len)
413 buf__sz = report_len;
414
415 dma_data = kmemdup(buf, buf__sz, GFP_KERNEL);
416 if (!dma_data)
417 return -ENOMEM;
418
419 ret = hid_bpf_ops->hid_hw_raw_request(hdev,
420 dma_data[0],
421 dma_data,
422 buf__sz,
423 rtype,
424 reqtype);
425
426 if (ret > 0)
427 memcpy(buf, dma_data, ret);
428
429 kfree(dma_data);
430 return ret;
431 }
432
433 /* our HID-BPF entrypoints */
434 BTF_SET8_START(hid_bpf_fmodret_ids)
435 BTF_ID_FLAGS(func, hid_bpf_device_event)
436 BTF_ID_FLAGS(func, hid_bpf_rdesc_fixup)
437 BTF_ID_FLAGS(func, __hid_bpf_tail_call)
438 BTF_SET8_END(hid_bpf_fmodret_ids)
439
440 static const struct btf_kfunc_id_set hid_bpf_fmodret_set = {
441 .owner = THIS_MODULE,
442 .set = &hid_bpf_fmodret_ids,
443 };
444
445 /* for syscall HID-BPF */
446 BTF_SET8_START(hid_bpf_syscall_kfunc_ids)
447 BTF_ID_FLAGS(func, hid_bpf_attach_prog)
448 BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL)
449 BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE)
450 BTF_ID_FLAGS(func, hid_bpf_hw_request)
451 BTF_SET8_END(hid_bpf_syscall_kfunc_ids)
452
453 static const struct btf_kfunc_id_set hid_bpf_syscall_kfunc_set = {
454 .owner = THIS_MODULE,
455 .set = &hid_bpf_syscall_kfunc_ids,
456 };
457
hid_bpf_connect_device(struct hid_device * hdev)458 int hid_bpf_connect_device(struct hid_device *hdev)
459 {
460 struct hid_bpf_prog_list *prog_list;
461
462 rcu_read_lock();
463 prog_list = rcu_dereference(hdev->bpf.progs[HID_BPF_PROG_TYPE_DEVICE_EVENT]);
464 rcu_read_unlock();
465
466 /* only allocate BPF data if there are programs attached */
467 if (!prog_list)
468 return 0;
469
470 return hid_bpf_allocate_event_data(hdev);
471 }
472 EXPORT_SYMBOL_GPL(hid_bpf_connect_device);
473
hid_bpf_disconnect_device(struct hid_device * hdev)474 void hid_bpf_disconnect_device(struct hid_device *hdev)
475 {
476 kfree(hdev->bpf.device_data);
477 hdev->bpf.device_data = NULL;
478 hdev->bpf.allocated_data = 0;
479 }
480 EXPORT_SYMBOL_GPL(hid_bpf_disconnect_device);
481
hid_bpf_destroy_device(struct hid_device * hdev)482 void hid_bpf_destroy_device(struct hid_device *hdev)
483 {
484 if (!hdev)
485 return;
486
487 /* mark the device as destroyed in bpf so we don't reattach it */
488 hdev->bpf.destroyed = true;
489
490 __hid_bpf_destroy_device(hdev);
491 }
492 EXPORT_SYMBOL_GPL(hid_bpf_destroy_device);
493
hid_bpf_device_init(struct hid_device * hdev)494 void hid_bpf_device_init(struct hid_device *hdev)
495 {
496 spin_lock_init(&hdev->bpf.progs_lock);
497 }
498 EXPORT_SYMBOL_GPL(hid_bpf_device_init);
499
hid_bpf_init(void)500 static int __init hid_bpf_init(void)
501 {
502 int err;
503
504 /* Note: if we exit with an error any time here, we would entirely break HID, which
505 * is probably not something we want. So we log an error and return success.
506 *
507 * This is not a big deal: the syscall allowing to attach a BPF program to a HID device
508 * will not be available, so nobody will be able to use the functionality.
509 */
510
511 err = register_btf_fmodret_id_set(&hid_bpf_fmodret_set);
512 if (err) {
513 pr_warn("error while registering fmodret entrypoints: %d", err);
514 return 0;
515 }
516
517 err = hid_bpf_preload_skel();
518 if (err) {
519 pr_warn("error while preloading HID BPF dispatcher: %d", err);
520 return 0;
521 }
522
523 /* register tracing kfuncs after we are sure we can load our preloaded bpf program */
524 err = register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &hid_bpf_kfunc_set);
525 if (err) {
526 pr_warn("error while setting HID BPF tracing kfuncs: %d", err);
527 return 0;
528 }
529
530 /* register syscalls after we are sure we can load our preloaded bpf program */
531 err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set);
532 if (err) {
533 pr_warn("error while setting HID BPF syscall kfuncs: %d", err);
534 return 0;
535 }
536
537 return 0;
538 }
539
hid_bpf_exit(void)540 static void __exit hid_bpf_exit(void)
541 {
542 /* HID depends on us, so if we hit that code, we are guaranteed that hid
543 * has been removed and thus we do not need to clear the HID devices
544 */
545 hid_bpf_free_links_and_skel();
546 }
547
548 late_initcall(hid_bpf_init);
549 module_exit(hid_bpf_exit);
550 MODULE_AUTHOR("Benjamin Tissoires");
551 MODULE_LICENSE("GPL");
552