1 // SPDX-License-Identifier: GPL-2.0-only
2
3 /*
4 * HID-BPF support for Linux
5 *
6 * Copyright (c) 2022-2024 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/overflow.h>
21 #include "hid_bpf_dispatch.h"
22
23 const struct hid_ops *hid_ops;
24 EXPORT_SYMBOL(hid_ops);
25
26 u8 *
dispatch_hid_bpf_device_event(struct hid_device * hdev,enum hid_report_type type,u8 * data,size_t * buf_size,u32 * size,int interrupt,u64 source,bool from_bpf)27 dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data,
28 size_t *buf_size, u32 *size, int interrupt, u64 source,
29 bool from_bpf)
30 {
31 struct hid_bpf_ctx_kern ctx_kern = {
32 .ctx = {
33 .hid = hdev,
34 .allocated_size = hdev->bpf.allocated_data,
35 .size = *size,
36 },
37 .data = hdev->bpf.device_data,
38 .from_bpf = from_bpf,
39 };
40 struct hid_bpf_ops *e;
41 int ret;
42
43 if (unlikely(hdev->bpf.destroyed))
44 return ERR_PTR(-ENODEV);
45
46 if (type >= HID_REPORT_TYPES)
47 return ERR_PTR(-EINVAL);
48
49 /* no program has been attached yet */
50 if (!hdev->bpf.device_data)
51 return data;
52
53 memset(ctx_kern.data, 0, hdev->bpf.allocated_data);
54 memcpy(ctx_kern.data, data, *size);
55
56 rcu_read_lock();
57 list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
58 if (e->hid_device_event) {
59 ret = e->hid_device_event(&ctx_kern.ctx, type, source);
60 if (ret < 0) {
61 rcu_read_unlock();
62 return ERR_PTR(ret);
63 }
64
65 if (ret)
66 ctx_kern.ctx.size = ret;
67 }
68 }
69 rcu_read_unlock();
70
71 ret = ctx_kern.ctx.size;
72 if (ret) {
73 if (ret > ctx_kern.ctx.allocated_size)
74 return ERR_PTR(-EINVAL);
75
76 *size = ret;
77 }
78
79 *buf_size = ctx_kern.ctx.allocated_size;
80 return ctx_kern.data;
81 }
82 EXPORT_SYMBOL_GPL(dispatch_hid_bpf_device_event);
83
dispatch_hid_bpf_raw_requests(struct hid_device * hdev,unsigned char reportnum,u8 * buf,u32 size,enum hid_report_type rtype,enum hid_class_request reqtype,u64 source,bool from_bpf)84 int dispatch_hid_bpf_raw_requests(struct hid_device *hdev,
85 unsigned char reportnum, u8 *buf,
86 u32 size, enum hid_report_type rtype,
87 enum hid_class_request reqtype,
88 u64 source, bool from_bpf)
89 {
90 struct hid_bpf_ctx_kern ctx_kern = {
91 .ctx = {
92 .hid = hdev,
93 .allocated_size = size,
94 .size = size,
95 },
96 .data = buf,
97 .from_bpf = from_bpf,
98 };
99 struct hid_bpf_ops *e;
100 int ret, idx;
101
102 if (unlikely(hdev->bpf.destroyed))
103 return -ENODEV;
104
105 if (rtype >= HID_REPORT_TYPES)
106 return -EINVAL;
107
108 idx = srcu_read_lock(&hdev->bpf.srcu);
109 list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list,
110 srcu_read_lock_held(&hdev->bpf.srcu)) {
111 if (!e->hid_hw_request)
112 continue;
113
114 ret = e->hid_hw_request(&ctx_kern.ctx, reportnum, rtype, reqtype, source);
115 if (ret)
116 goto out;
117 }
118 ret = 0;
119
120 out:
121 srcu_read_unlock(&hdev->bpf.srcu, idx);
122 return ret;
123 }
124 EXPORT_SYMBOL_GPL(dispatch_hid_bpf_raw_requests);
125
dispatch_hid_bpf_output_report(struct hid_device * hdev,__u8 * buf,u32 size,u64 source,bool from_bpf)126 int dispatch_hid_bpf_output_report(struct hid_device *hdev,
127 __u8 *buf, u32 size, u64 source,
128 bool from_bpf)
129 {
130 struct hid_bpf_ctx_kern ctx_kern = {
131 .ctx = {
132 .hid = hdev,
133 .allocated_size = size,
134 .size = size,
135 },
136 .data = buf,
137 .from_bpf = from_bpf,
138 };
139 struct hid_bpf_ops *e;
140 int ret, idx;
141
142 if (unlikely(hdev->bpf.destroyed))
143 return -ENODEV;
144
145 idx = srcu_read_lock(&hdev->bpf.srcu);
146 list_for_each_entry_srcu(e, &hdev->bpf.prog_list, list,
147 srcu_read_lock_held(&hdev->bpf.srcu)) {
148 if (!e->hid_hw_output_report)
149 continue;
150
151 ret = e->hid_hw_output_report(&ctx_kern.ctx, source);
152 if (ret)
153 goto out;
154 }
155 ret = 0;
156
157 out:
158 srcu_read_unlock(&hdev->bpf.srcu, idx);
159 return ret;
160 }
161 EXPORT_SYMBOL_GPL(dispatch_hid_bpf_output_report);
162
call_hid_bpf_rdesc_fixup(struct hid_device * hdev,const u8 * rdesc,unsigned int * size)163 const u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size)
164 {
165 int ret;
166 struct hid_bpf_ctx_kern ctx_kern = {
167 .ctx = {
168 .hid = hdev,
169 .size = *size,
170 .allocated_size = HID_MAX_DESCRIPTOR_SIZE,
171 },
172 };
173
174 if (!hdev->bpf.rdesc_ops)
175 goto ignore_bpf;
176
177 ctx_kern.data = kzalloc(ctx_kern.ctx.allocated_size, GFP_KERNEL);
178 if (!ctx_kern.data)
179 goto ignore_bpf;
180
181 memcpy(ctx_kern.data, rdesc, min_t(unsigned int, *size, HID_MAX_DESCRIPTOR_SIZE));
182
183 ret = hdev->bpf.rdesc_ops->hid_rdesc_fixup(&ctx_kern.ctx);
184 if (ret < 0)
185 goto ignore_bpf;
186
187 if (ret) {
188 if (ret > ctx_kern.ctx.allocated_size)
189 goto ignore_bpf;
190
191 *size = ret;
192 }
193
194 return krealloc(ctx_kern.data, *size, GFP_KERNEL);
195
196 ignore_bpf:
197 kfree(ctx_kern.data);
198 return rdesc;
199 }
200 EXPORT_SYMBOL_GPL(call_hid_bpf_rdesc_fixup);
201
device_match_id(struct device * dev,const void * id)202 static int device_match_id(struct device *dev, const void *id)
203 {
204 struct hid_device *hdev = to_hid_device(dev);
205
206 return hdev->id == *(int *)id;
207 }
208
hid_get_device(unsigned int hid_id)209 struct hid_device *hid_get_device(unsigned int hid_id)
210 {
211 struct device *dev;
212
213 if (!hid_ops)
214 return ERR_PTR(-EINVAL);
215
216 dev = bus_find_device(hid_ops->bus_type, NULL, &hid_id, device_match_id);
217 if (!dev)
218 return ERR_PTR(-EINVAL);
219
220 return to_hid_device(dev);
221 }
222
hid_put_device(struct hid_device * hid)223 void hid_put_device(struct hid_device *hid)
224 {
225 put_device(&hid->dev);
226 }
227
__hid_bpf_allocate_data(struct hid_device * hdev,u8 ** data,u32 * size)228 static int __hid_bpf_allocate_data(struct hid_device *hdev, u8 **data, u32 *size)
229 {
230 u8 *alloc_data;
231 unsigned int i, j, max_report_len = 0;
232 size_t alloc_size = 0;
233
234 /* compute the maximum report length for this device */
235 for (i = 0; i < HID_REPORT_TYPES; i++) {
236 struct hid_report_enum *report_enum = hdev->report_enum + i;
237
238 for (j = 0; j < HID_MAX_IDS; j++) {
239 struct hid_report *report = report_enum->report_id_hash[j];
240
241 if (report)
242 max_report_len = max(max_report_len, hid_report_len(report));
243 }
244 }
245
246 /*
247 * Give us a little bit of extra space and some predictability in the
248 * buffer length we create. This way, we can tell users that they can
249 * work on chunks of 64 bytes of memory without having the bpf verifier
250 * scream at them.
251 */
252 alloc_size = DIV_ROUND_UP(max_report_len, 64) * 64;
253
254 alloc_data = kzalloc(alloc_size, GFP_KERNEL);
255 if (!alloc_data)
256 return -ENOMEM;
257
258 *data = alloc_data;
259 *size = alloc_size;
260
261 return 0;
262 }
263
hid_bpf_allocate_event_data(struct hid_device * hdev)264 int hid_bpf_allocate_event_data(struct hid_device *hdev)
265 {
266 /* hdev->bpf.device_data is already allocated, abort */
267 if (hdev->bpf.device_data)
268 return 0;
269
270 return __hid_bpf_allocate_data(hdev, &hdev->bpf.device_data, &hdev->bpf.allocated_data);
271 }
272
hid_bpf_reconnect(struct hid_device * hdev)273 int hid_bpf_reconnect(struct hid_device *hdev)
274 {
275 if (!test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status)) {
276 /* trigger call to call_hid_bpf_rdesc_fixup() during the next probe */
277 hdev->bpf_rsize = 0;
278 return device_reprobe(&hdev->dev);
279 }
280
281 return 0;
282 }
283
284 /* Disables missing prototype warnings */
285 __bpf_kfunc_start_defs();
286
287 /**
288 * hid_bpf_get_data - Get the kernel memory pointer associated with the context @ctx
289 *
290 * @ctx: The HID-BPF context
291 * @offset: The offset within the memory
292 * @rdwr_buf_size: the const size of the buffer
293 *
294 * @returns %NULL on error, an %__u8 memory pointer on success
295 */
296 __bpf_kfunc __u8 *
hid_bpf_get_data(struct hid_bpf_ctx * ctx,unsigned int offset,const size_t rdwr_buf_size)297 hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr_buf_size)
298 {
299 struct hid_bpf_ctx_kern *ctx_kern;
300 size_t end;
301
302 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
303
304 if (check_add_overflow(rdwr_buf_size, offset, &end) ||
305 end > ctx->allocated_size)
306 return NULL;
307
308 return ctx_kern->data + offset;
309 }
310
311 /**
312 * hid_bpf_allocate_context - Allocate a context to the given HID device
313 *
314 * @hid_id: the system unique identifier of the HID device
315 *
316 * @returns A pointer to &struct hid_bpf_ctx on success, %NULL on error.
317 */
318 __bpf_kfunc struct hid_bpf_ctx *
hid_bpf_allocate_context(unsigned int hid_id)319 hid_bpf_allocate_context(unsigned int hid_id)
320 {
321 struct hid_device *hdev;
322 struct hid_bpf_ctx_kern *ctx_kern = NULL;
323
324 hdev = hid_get_device(hid_id);
325 if (IS_ERR(hdev))
326 return NULL;
327
328 ctx_kern = kzalloc_obj(*ctx_kern);
329 if (!ctx_kern) {
330 hid_put_device(hdev);
331 return NULL;
332 }
333
334 ctx_kern->ctx.hid = hdev;
335
336 return &ctx_kern->ctx;
337 }
338
339 /**
340 * hid_bpf_release_context - Release the previously allocated context @ctx
341 *
342 * @ctx: the HID-BPF context to release
343 *
344 */
345 __bpf_kfunc void
hid_bpf_release_context(struct hid_bpf_ctx * ctx)346 hid_bpf_release_context(struct hid_bpf_ctx *ctx)
347 {
348 struct hid_bpf_ctx_kern *ctx_kern;
349 struct hid_device *hid;
350
351 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
352 hid = (struct hid_device *)ctx_kern->ctx.hid; /* ignore const */
353
354 kfree(ctx_kern);
355
356 /* get_device() is called by bus_find_device() */
357 hid_put_device(hid);
358 }
359
360 static int
__hid_bpf_hw_check_params(struct hid_bpf_ctx * ctx,__u8 * buf,size_t * buf__sz,enum hid_report_type rtype)361 __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz,
362 enum hid_report_type rtype)
363 {
364 struct hid_report_enum *report_enum;
365 struct hid_report *report;
366 u32 report_len;
367
368 /* check arguments */
369 if (!hid_ops)
370 return -EINVAL;
371
372 switch (rtype) {
373 case HID_INPUT_REPORT:
374 case HID_OUTPUT_REPORT:
375 case HID_FEATURE_REPORT:
376 break;
377 default:
378 return -EINVAL;
379 }
380
381 if (*buf__sz < 1)
382 return -EINVAL;
383
384 report_enum = ctx->hid->report_enum + rtype;
385 report = hid_ops->hid_get_report(report_enum, buf);
386 if (!report)
387 return -EINVAL;
388
389 report_len = hid_report_len(report);
390
391 if (*buf__sz > report_len)
392 *buf__sz = report_len;
393
394 return 0;
395 }
396
397 /**
398 * hid_bpf_hw_request - Communicate with a HID device
399 *
400 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
401 * @buf: a %PTR_TO_MEM buffer
402 * @buf__sz: the size of the data to transfer
403 * @rtype: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
404 * @reqtype: the type of the request (%HID_REQ_GET_REPORT, %HID_REQ_SET_REPORT, ...)
405 *
406 * @returns %0 on success, a negative error code otherwise.
407 */
408 __bpf_kfunc 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)409 hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
410 enum hid_report_type rtype, enum hid_class_request reqtype)
411 {
412 struct hid_bpf_ctx_kern *ctx_kern;
413 size_t size = buf__sz;
414 u8 *dma_data;
415 int ret;
416
417 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
418
419 if (ctx_kern->from_bpf)
420 return -EDEADLOCK;
421
422 /* check arguments */
423 ret = __hid_bpf_hw_check_params(ctx, buf, &size, rtype);
424 if (ret)
425 return ret;
426
427 switch (reqtype) {
428 case HID_REQ_GET_REPORT:
429 case HID_REQ_GET_IDLE:
430 case HID_REQ_GET_PROTOCOL:
431 case HID_REQ_SET_REPORT:
432 case HID_REQ_SET_IDLE:
433 case HID_REQ_SET_PROTOCOL:
434 break;
435 default:
436 return -EINVAL;
437 }
438
439 dma_data = kmemdup(buf, size, GFP_KERNEL);
440 if (!dma_data)
441 return -ENOMEM;
442
443 ret = hid_ops->hid_hw_raw_request(ctx->hid,
444 dma_data[0],
445 dma_data,
446 size,
447 rtype,
448 reqtype,
449 (u64)(long)ctx,
450 true); /* prevent infinite recursions */
451
452 if (ret > size)
453 ret = size;
454 if (ret > 0)
455 memcpy(buf, dma_data, ret);
456
457 kfree(dma_data);
458 return ret;
459 }
460
461 /**
462 * hid_bpf_hw_output_report - Send an output report to a HID device
463 *
464 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
465 * @buf: a %PTR_TO_MEM buffer
466 * @buf__sz: the size of the data to transfer
467 *
468 * Returns the number of bytes transferred on success, a negative error code otherwise.
469 */
470 __bpf_kfunc int
hid_bpf_hw_output_report(struct hid_bpf_ctx * ctx,__u8 * buf,size_t buf__sz)471 hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz)
472 {
473 struct hid_bpf_ctx_kern *ctx_kern;
474 size_t size = buf__sz;
475 u8 *dma_data;
476 int ret;
477
478 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
479 if (ctx_kern->from_bpf)
480 return -EDEADLOCK;
481
482 /* check arguments */
483 ret = __hid_bpf_hw_check_params(ctx, buf, &size, HID_OUTPUT_REPORT);
484 if (ret)
485 return ret;
486
487 dma_data = kmemdup(buf, size, GFP_KERNEL);
488 if (!dma_data)
489 return -ENOMEM;
490
491 ret = hid_ops->hid_hw_output_report(ctx->hid, dma_data, size, (u64)(long)ctx, true);
492
493 kfree(dma_data);
494 return ret;
495 }
496
497 static int
__hid_bpf_input_report(struct hid_bpf_ctx * ctx,enum hid_report_type type,u8 * buf,size_t size,bool lock_already_taken)498 __hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
499 size_t size, bool lock_already_taken)
500 {
501 struct hid_bpf_ctx_kern *ctx_kern;
502 int ret;
503
504 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
505 if (ctx_kern->from_bpf)
506 return -EDEADLOCK;
507
508 /* check arguments */
509 ret = __hid_bpf_hw_check_params(ctx, buf, &size, type);
510 if (ret)
511 return ret;
512
513 return hid_ops->hid_input_report(ctx->hid, type, buf, size, size, 0, (u64)(long)ctx, true,
514 lock_already_taken);
515 }
516
517 /**
518 * hid_bpf_try_input_report - Inject a HID report in the kernel from a HID device
519 *
520 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
521 * @type: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
522 * @buf: a %PTR_TO_MEM buffer
523 * @buf__sz: the size of the data to transfer
524 *
525 * Returns %0 on success, a negative error code otherwise. This function will immediately
526 * fail if the device is not available, thus can be safely used in IRQ context.
527 */
528 __bpf_kfunc int
hid_bpf_try_input_report(struct hid_bpf_ctx * ctx,enum hid_report_type type,u8 * buf,const size_t buf__sz)529 hid_bpf_try_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
530 const size_t buf__sz)
531 {
532 struct hid_bpf_ctx_kern *ctx_kern;
533 bool from_hid_event_hook;
534
535 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
536 from_hid_event_hook = ctx_kern->data && ctx_kern->data == ctx->hid->bpf.device_data;
537
538 return __hid_bpf_input_report(ctx, type, buf, buf__sz, from_hid_event_hook);
539 }
540
541 /**
542 * hid_bpf_input_report - Inject a HID report in the kernel from a HID device
543 *
544 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
545 * @type: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
546 * @buf: a %PTR_TO_MEM buffer
547 * @buf__sz: the size of the data to transfer
548 *
549 * Returns %0 on success, a negative error code otherwise. This function will wait for the
550 * device to be available before injecting the event, thus needs to be called in sleepable
551 * context.
552 */
553 __bpf_kfunc int
hid_bpf_input_report(struct hid_bpf_ctx * ctx,enum hid_report_type type,u8 * buf,const size_t buf__sz)554 hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
555 const size_t buf__sz)
556 {
557 int ret;
558
559 ret = down_interruptible(&ctx->hid->driver_input_lock);
560 if (ret)
561 return ret;
562
563 /* check arguments */
564 ret = __hid_bpf_input_report(ctx, type, buf, buf__sz, true /* lock_already_taken */);
565
566 up(&ctx->hid->driver_input_lock);
567
568 return ret;
569 }
570 __bpf_kfunc_end_defs();
571
572 /*
573 * The following set contains all functions we agree BPF programs
574 * can use.
575 */
576 BTF_KFUNCS_START(hid_bpf_kfunc_ids)
577 BTF_ID_FLAGS(func, hid_bpf_get_data, KF_RET_NULL)
578 BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
579 BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE | KF_SLEEPABLE)
580 BTF_ID_FLAGS(func, hid_bpf_hw_request, KF_SLEEPABLE)
581 BTF_ID_FLAGS(func, hid_bpf_hw_output_report, KF_SLEEPABLE)
582 BTF_ID_FLAGS(func, hid_bpf_input_report, KF_SLEEPABLE)
583 BTF_ID_FLAGS(func, hid_bpf_try_input_report)
584 BTF_KFUNCS_END(hid_bpf_kfunc_ids)
585
586 static const struct btf_kfunc_id_set hid_bpf_kfunc_set = {
587 .owner = THIS_MODULE,
588 .set = &hid_bpf_kfunc_ids,
589 };
590
591 /* for syscall HID-BPF */
592 BTF_KFUNCS_START(hid_bpf_syscall_kfunc_ids)
593 BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
594 BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE | KF_SLEEPABLE)
595 BTF_ID_FLAGS(func, hid_bpf_hw_request, KF_SLEEPABLE)
596 BTF_ID_FLAGS(func, hid_bpf_hw_output_report, KF_SLEEPABLE)
597 BTF_ID_FLAGS(func, hid_bpf_input_report, KF_SLEEPABLE)
598 BTF_KFUNCS_END(hid_bpf_syscall_kfunc_ids)
599
600 static const struct btf_kfunc_id_set hid_bpf_syscall_kfunc_set = {
601 .owner = THIS_MODULE,
602 .set = &hid_bpf_syscall_kfunc_ids,
603 };
604
hid_bpf_connect_device(struct hid_device * hdev)605 int hid_bpf_connect_device(struct hid_device *hdev)
606 {
607 bool need_to_allocate = false;
608 struct hid_bpf_ops *e;
609
610 rcu_read_lock();
611 list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
612 if (e->hid_device_event) {
613 need_to_allocate = true;
614 break;
615 }
616 }
617 rcu_read_unlock();
618
619 /* only allocate BPF data if there are programs attached */
620 if (!need_to_allocate)
621 return 0;
622
623 return hid_bpf_allocate_event_data(hdev);
624 }
625 EXPORT_SYMBOL_GPL(hid_bpf_connect_device);
626
hid_bpf_disconnect_device(struct hid_device * hdev)627 void hid_bpf_disconnect_device(struct hid_device *hdev)
628 {
629 kfree(hdev->bpf.device_data);
630 hdev->bpf.device_data = NULL;
631 hdev->bpf.allocated_data = 0;
632 }
633 EXPORT_SYMBOL_GPL(hid_bpf_disconnect_device);
634
hid_bpf_destroy_device(struct hid_device * hdev)635 void hid_bpf_destroy_device(struct hid_device *hdev)
636 {
637 if (!hdev)
638 return;
639
640 /* mark the device as destroyed in bpf so we don't reattach it */
641 hdev->bpf.destroyed = true;
642
643 __hid_bpf_ops_destroy_device(hdev);
644
645 synchronize_srcu(&hdev->bpf.srcu);
646 cleanup_srcu_struct(&hdev->bpf.srcu);
647 }
648 EXPORT_SYMBOL_GPL(hid_bpf_destroy_device);
649
hid_bpf_device_init(struct hid_device * hdev)650 int hid_bpf_device_init(struct hid_device *hdev)
651 {
652 INIT_LIST_HEAD(&hdev->bpf.prog_list);
653 mutex_init(&hdev->bpf.prog_list_lock);
654 return init_srcu_struct(&hdev->bpf.srcu);
655 }
656 EXPORT_SYMBOL_GPL(hid_bpf_device_init);
657
hid_bpf_init(void)658 static int __init hid_bpf_init(void)
659 {
660 int err;
661
662 /* Note: if we exit with an error any time here, we would entirely break HID, which
663 * is probably not something we want. So we log an error and return success.
664 *
665 * This is not a big deal: nobody will be able to use the functionality.
666 */
667
668 err = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &hid_bpf_kfunc_set);
669 if (err) {
670 pr_warn("error while setting HID BPF tracing kfuncs: %d", err);
671 return 0;
672 }
673
674 err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set);
675 if (err) {
676 pr_warn("error while setting HID BPF syscall kfuncs: %d", err);
677 return 0;
678 }
679
680 return 0;
681 }
682
683 late_initcall(hid_bpf_init);
684 MODULE_AUTHOR("Benjamin Tissoires");
685 MODULE_LICENSE("GPL");
686