1 // SPDX-License-Identifier: GPL-2.0-only
4 * HID-BPF support for Linux
6 * Copyright (c) 2022-2024 Benjamin Tissoires
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 "hid_bpf_dispatch.h"
22 const struct hid_ops *hid_ops;
23 EXPORT_SYMBOL(hid_ops);
26 dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data,
27 u32 *size, int interrupt, u64 source, bool from_bpf)
29 struct hid_bpf_ctx_kern ctx_kern = {
32 .allocated_size = hdev->bpf.allocated_data,
35 .data = hdev->bpf.device_data,
38 struct hid_bpf_ops *e;
41 if (type >= HID_REPORT_TYPES)
42 return ERR_PTR(-EINVAL);
44 /* no program has been attached yet */
45 if (!hdev->bpf.device_data)
48 memset(ctx_kern.data, 0, hdev->bpf.allocated_data);
49 memcpy(ctx_kern.data, data, *size);
52 list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
53 if (e->hid_device_event) {
54 ret = e->hid_device_event(&ctx_kern.ctx, type, source);
61 ctx_kern.ctx.size = ret;
66 ret = ctx_kern.ctx.size;
68 if (ret > ctx_kern.ctx.allocated_size)
69 return ERR_PTR(-EINVAL);
76 EXPORT_SYMBOL_GPL(dispatch_hid_bpf_device_event);
78 int dispatch_hid_bpf_raw_requests(struct hid_device *hdev,
79 unsigned char reportnum, u8 *buf,
80 u32 size, enum hid_report_type rtype,
81 enum hid_class_request reqtype,
82 u64 source, bool from_bpf)
84 struct hid_bpf_ctx_kern ctx_kern = {
87 .allocated_size = size,
93 struct hid_bpf_ops *e;
96 if (rtype >= HID_REPORT_TYPES)
99 idx = srcu_read_lock(&hdev->bpf.srcu);
100 list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list,
101 srcu_read_lock_held(&hdev->bpf.srcu)) {
102 if (!e->hid_hw_request)
105 ret = e->hid_hw_request(&ctx_kern.ctx, reportnum, rtype, reqtype, source);
112 srcu_read_unlock(&hdev->bpf.srcu, idx);
115 EXPORT_SYMBOL_GPL(dispatch_hid_bpf_raw_requests);
117 int dispatch_hid_bpf_output_report(struct hid_device *hdev,
118 __u8 *buf, u32 size, u64 source,
121 struct hid_bpf_ctx_kern ctx_kern = {
124 .allocated_size = size,
128 .from_bpf = from_bpf,
130 struct hid_bpf_ops *e;
133 idx = srcu_read_lock(&hdev->bpf.srcu);
134 list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list,
135 srcu_read_lock_held(&hdev->bpf.srcu)) {
136 if (!e->hid_hw_output_report)
139 ret = e->hid_hw_output_report(&ctx_kern.ctx, source);
146 srcu_read_unlock(&hdev->bpf.srcu, idx);
149 EXPORT_SYMBOL_GPL(dispatch_hid_bpf_output_report);
151 const u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size)
154 struct hid_bpf_ctx_kern ctx_kern = {
158 .allocated_size = HID_MAX_DESCRIPTOR_SIZE,
162 if (!hdev->bpf.rdesc_ops)
165 ctx_kern.data = kzalloc(ctx_kern.ctx.allocated_size, GFP_KERNEL);
169 memcpy(ctx_kern.data, rdesc, min_t(unsigned int, *size, HID_MAX_DESCRIPTOR_SIZE));
171 ret = hdev->bpf.rdesc_ops->hid_rdesc_fixup(&ctx_kern.ctx);
176 if (ret > ctx_kern.ctx.allocated_size)
182 return krealloc(ctx_kern.data, *size, GFP_KERNEL);
185 kfree(ctx_kern.data);
188 EXPORT_SYMBOL_GPL(call_hid_bpf_rdesc_fixup);
190 static int device_match_id(struct device *dev, const void *id)
192 struct hid_device *hdev = to_hid_device(dev);
194 return hdev->id == *(int *)id;
197 struct hid_device *hid_get_device(unsigned int hid_id)
202 return ERR_PTR(-EINVAL);
204 dev = bus_find_device(hid_ops->bus_type, NULL, &hid_id, device_match_id);
206 return ERR_PTR(-EINVAL);
208 return to_hid_device(dev);
211 void hid_put_device(struct hid_device *hid)
213 put_device(&hid->dev);
216 static int __hid_bpf_allocate_data(struct hid_device *hdev, u8 **data, u32 *size)
219 unsigned int i, j, max_report_len = 0;
220 size_t alloc_size = 0;
222 /* compute the maximum report length for this device */
223 for (i = 0; i < HID_REPORT_TYPES; i++) {
224 struct hid_report_enum *report_enum = hdev->report_enum + i;
226 for (j = 0; j < HID_MAX_IDS; j++) {
227 struct hid_report *report = report_enum->report_id_hash[j];
230 max_report_len = max(max_report_len, hid_report_len(report));
235 * Give us a little bit of extra space and some predictability in the
236 * buffer length we create. This way, we can tell users that they can
237 * work on chunks of 64 bytes of memory without having the bpf verifier
240 alloc_size = DIV_ROUND_UP(max_report_len, 64) * 64;
242 alloc_data = kzalloc(alloc_size, GFP_KERNEL);
252 int hid_bpf_allocate_event_data(struct hid_device *hdev)
254 /* hdev->bpf.device_data is already allocated, abort */
255 if (hdev->bpf.device_data)
258 return __hid_bpf_allocate_data(hdev, &hdev->bpf.device_data, &hdev->bpf.allocated_data);
261 int hid_bpf_reconnect(struct hid_device *hdev)
263 if (!test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status)) {
264 /* trigger call to call_hid_bpf_rdesc_fixup() during the next probe */
266 return device_reprobe(&hdev->dev);
272 /* Disables missing prototype warnings */
273 __bpf_kfunc_start_defs();
276 * hid_bpf_get_data - Get the kernel memory pointer associated with the context @ctx
278 * @ctx: The HID-BPF context
279 * @offset: The offset within the memory
280 * @rdwr_buf_size: the const size of the buffer
282 * @returns %NULL on error, an %__u8 memory pointer on success
285 hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr_buf_size)
287 struct hid_bpf_ctx_kern *ctx_kern;
292 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
294 if (rdwr_buf_size + offset > ctx->allocated_size)
297 return ctx_kern->data + offset;
301 * hid_bpf_allocate_context - Allocate a context to the given HID device
303 * @hid_id: the system unique identifier of the HID device
305 * @returns A pointer to &struct hid_bpf_ctx on success, %NULL on error.
307 __bpf_kfunc struct hid_bpf_ctx *
308 hid_bpf_allocate_context(unsigned int hid_id)
310 struct hid_device *hdev;
311 struct hid_bpf_ctx_kern *ctx_kern = NULL;
313 hdev = hid_get_device(hid_id);
317 ctx_kern = kzalloc(sizeof(*ctx_kern), GFP_KERNEL);
319 hid_put_device(hdev);
323 ctx_kern->ctx.hid = hdev;
325 return &ctx_kern->ctx;
329 * hid_bpf_release_context - Release the previously allocated context @ctx
331 * @ctx: the HID-BPF context to release
335 hid_bpf_release_context(struct hid_bpf_ctx *ctx)
337 struct hid_bpf_ctx_kern *ctx_kern;
338 struct hid_device *hid;
340 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
341 hid = (struct hid_device *)ctx_kern->ctx.hid; /* ignore const */
345 /* get_device() is called by bus_find_device() */
350 __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz,
351 enum hid_report_type rtype)
353 struct hid_report_enum *report_enum;
354 struct hid_report *report;
357 /* check arguments */
358 if (!ctx || !hid_ops || !buf)
362 case HID_INPUT_REPORT:
363 case HID_OUTPUT_REPORT:
364 case HID_FEATURE_REPORT:
373 report_enum = ctx->hid->report_enum + rtype;
374 report = hid_ops->hid_get_report(report_enum, buf);
378 report_len = hid_report_len(report);
380 if (*buf__sz > report_len)
381 *buf__sz = report_len;
387 * hid_bpf_hw_request - Communicate with a HID device
389 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
390 * @buf: a %PTR_TO_MEM buffer
391 * @buf__sz: the size of the data to transfer
392 * @rtype: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
393 * @reqtype: the type of the request (%HID_REQ_GET_REPORT, %HID_REQ_SET_REPORT, ...)
395 * @returns %0 on success, a negative error code otherwise.
398 hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
399 enum hid_report_type rtype, enum hid_class_request reqtype)
401 struct hid_bpf_ctx_kern *ctx_kern;
402 size_t size = buf__sz;
406 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
408 if (ctx_kern->from_bpf)
411 /* check arguments */
412 ret = __hid_bpf_hw_check_params(ctx, buf, &size, rtype);
417 case HID_REQ_GET_REPORT:
418 case HID_REQ_GET_IDLE:
419 case HID_REQ_GET_PROTOCOL:
420 case HID_REQ_SET_REPORT:
421 case HID_REQ_SET_IDLE:
422 case HID_REQ_SET_PROTOCOL:
428 dma_data = kmemdup(buf, size, GFP_KERNEL);
432 ret = hid_ops->hid_hw_raw_request(ctx->hid,
439 true); /* prevent infinite recursions */
442 memcpy(buf, dma_data, ret);
449 * hid_bpf_hw_output_report - Send an output report to a HID device
451 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
452 * @buf: a %PTR_TO_MEM buffer
453 * @buf__sz: the size of the data to transfer
455 * Returns the number of bytes transferred on success, a negative error code otherwise.
458 hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz)
460 struct hid_bpf_ctx_kern *ctx_kern;
461 size_t size = buf__sz;
465 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
466 if (ctx_kern->from_bpf)
469 /* check arguments */
470 ret = __hid_bpf_hw_check_params(ctx, buf, &size, HID_OUTPUT_REPORT);
474 dma_data = kmemdup(buf, size, GFP_KERNEL);
478 ret = hid_ops->hid_hw_output_report(ctx->hid, dma_data, size, (u64)(long)ctx, true);
485 __hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
486 size_t size, bool lock_already_taken)
488 struct hid_bpf_ctx_kern *ctx_kern;
491 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
492 if (ctx_kern->from_bpf)
495 /* check arguments */
496 ret = __hid_bpf_hw_check_params(ctx, buf, &size, type);
500 return hid_ops->hid_input_report(ctx->hid, type, buf, size, 0, (u64)(long)ctx, true,
505 * hid_bpf_try_input_report - Inject a HID report in the kernel from a HID device
507 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
508 * @type: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
509 * @buf: a %PTR_TO_MEM buffer
510 * @buf__sz: the size of the data to transfer
512 * Returns %0 on success, a negative error code otherwise. This function will immediately
513 * fail if the device is not available, thus can be safely used in IRQ context.
516 hid_bpf_try_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
517 const size_t buf__sz)
519 struct hid_bpf_ctx_kern *ctx_kern;
520 bool from_hid_event_hook;
522 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
523 from_hid_event_hook = ctx_kern->data && ctx_kern->data == ctx->hid->bpf.device_data;
525 return __hid_bpf_input_report(ctx, type, buf, buf__sz, from_hid_event_hook);
529 * hid_bpf_input_report - Inject a HID report in the kernel from a HID device
531 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
532 * @type: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
533 * @buf: a %PTR_TO_MEM buffer
534 * @buf__sz: the size of the data to transfer
536 * Returns %0 on success, a negative error code otherwise. This function will wait for the
537 * device to be available before injecting the event, thus needs to be called in sleepable
541 hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
542 const size_t buf__sz)
546 ret = down_interruptible(&ctx->hid->driver_input_lock);
550 /* check arguments */
551 ret = __hid_bpf_input_report(ctx, type, buf, buf__sz, true /* lock_already_taken */);
553 up(&ctx->hid->driver_input_lock);
557 __bpf_kfunc_end_defs();
560 * The following set contains all functions we agree BPF programs
563 BTF_KFUNCS_START(hid_bpf_kfunc_ids)
564 BTF_ID_FLAGS(func, hid_bpf_get_data, KF_RET_NULL)
565 BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
566 BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE | KF_SLEEPABLE)
567 BTF_ID_FLAGS(func, hid_bpf_hw_request, KF_SLEEPABLE)
568 BTF_ID_FLAGS(func, hid_bpf_hw_output_report, KF_SLEEPABLE)
569 BTF_ID_FLAGS(func, hid_bpf_input_report, KF_SLEEPABLE)
570 BTF_ID_FLAGS(func, hid_bpf_try_input_report)
571 BTF_KFUNCS_END(hid_bpf_kfunc_ids)
573 static const struct btf_kfunc_id_set hid_bpf_kfunc_set = {
574 .owner = THIS_MODULE,
575 .set = &hid_bpf_kfunc_ids,
578 /* for syscall HID-BPF */
579 BTF_KFUNCS_START(hid_bpf_syscall_kfunc_ids)
580 BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL)
581 BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE)
582 BTF_ID_FLAGS(func, hid_bpf_hw_request)
583 BTF_ID_FLAGS(func, hid_bpf_hw_output_report)
584 BTF_ID_FLAGS(func, hid_bpf_input_report)
585 BTF_KFUNCS_END(hid_bpf_syscall_kfunc_ids)
587 static const struct btf_kfunc_id_set hid_bpf_syscall_kfunc_set = {
588 .owner = THIS_MODULE,
589 .set = &hid_bpf_syscall_kfunc_ids,
592 int hid_bpf_connect_device(struct hid_device *hdev)
594 bool need_to_allocate = false;
595 struct hid_bpf_ops *e;
598 list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
599 if (e->hid_device_event) {
600 need_to_allocate = true;
606 /* only allocate BPF data if there are programs attached */
607 if (!need_to_allocate)
610 return hid_bpf_allocate_event_data(hdev);
612 EXPORT_SYMBOL_GPL(hid_bpf_connect_device);
614 void hid_bpf_disconnect_device(struct hid_device *hdev)
616 kfree(hdev->bpf.device_data);
617 hdev->bpf.device_data = NULL;
618 hdev->bpf.allocated_data = 0;
620 EXPORT_SYMBOL_GPL(hid_bpf_disconnect_device);
622 void hid_bpf_destroy_device(struct hid_device *hdev)
627 /* mark the device as destroyed in bpf so we don't reattach it */
628 hdev->bpf.destroyed = true;
630 __hid_bpf_ops_destroy_device(hdev);
632 synchronize_srcu(&hdev->bpf.srcu);
633 cleanup_srcu_struct(&hdev->bpf.srcu);
635 EXPORT_SYMBOL_GPL(hid_bpf_destroy_device);
637 int hid_bpf_device_init(struct hid_device *hdev)
639 INIT_LIST_HEAD(&hdev->bpf.prog_list);
640 mutex_init(&hdev->bpf.prog_list_lock);
641 return init_srcu_struct(&hdev->bpf.srcu);
643 EXPORT_SYMBOL_GPL(hid_bpf_device_init);
645 static int __init hid_bpf_init(void)
649 /* Note: if we exit with an error any time here, we would entirely break HID, which
650 * is probably not something we want. So we log an error and return success.
652 * This is not a big deal: nobody will be able to use the functionality.
655 err = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &hid_bpf_kfunc_set);
657 pr_warn("error while setting HID BPF tracing kfuncs: %d", err);
661 err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set);
663 pr_warn("error while setting HID BPF syscall kfuncs: %d", err);
670 late_initcall(hid_bpf_init);
671 MODULE_AUTHOR("Benjamin Tissoires");
672 MODULE_LICENSE("GPL");