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