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,bool hw_request)361 __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz,
362 enum hid_report_type rtype, bool hw_request)
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 /* unnumbered reports need to have a report ID reserved in the first byte */
392 if (hw_request && report_enum->numbered == 0)
393 report_len += 1;
394
395 if (*buf__sz > report_len)
396 *buf__sz = report_len;
397
398 return 0;
399 }
400
401 /**
402 * hid_bpf_hw_request - Communicate with a HID device
403 *
404 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
405 * @buf: a %PTR_TO_MEM buffer
406 * @buf__sz: the size of the data to transfer
407 * @rtype: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
408 * @reqtype: the type of the request (%HID_REQ_GET_REPORT, %HID_REQ_SET_REPORT, ...)
409 *
410 * @returns %0 on success, a negative error code otherwise.
411 */
412 __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)413 hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
414 enum hid_report_type rtype, enum hid_class_request reqtype)
415 {
416 struct hid_bpf_ctx_kern *ctx_kern;
417 size_t size = buf__sz;
418 u8 *dma_data;
419 int ret;
420
421 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
422
423 if (ctx_kern->from_bpf)
424 return -EDEADLOCK;
425
426 /* check arguments */
427 ret = __hid_bpf_hw_check_params(ctx, buf, &size, rtype, true);
428 if (ret)
429 return ret;
430
431 switch (reqtype) {
432 case HID_REQ_GET_REPORT:
433 case HID_REQ_GET_IDLE:
434 case HID_REQ_GET_PROTOCOL:
435 case HID_REQ_SET_REPORT:
436 case HID_REQ_SET_IDLE:
437 case HID_REQ_SET_PROTOCOL:
438 break;
439 default:
440 return -EINVAL;
441 }
442
443 dma_data = kmemdup(buf, size, GFP_KERNEL);
444 if (!dma_data)
445 return -ENOMEM;
446
447 ret = hid_ops->hid_hw_raw_request(ctx->hid,
448 dma_data[0],
449 dma_data,
450 size,
451 rtype,
452 reqtype,
453 (u64)(long)ctx,
454 true); /* prevent infinite recursions */
455
456 if (ret > size)
457 ret = size;
458 if (ret > 0)
459 memcpy(buf, dma_data, ret);
460
461 kfree(dma_data);
462 return ret;
463 }
464
465 /**
466 * hid_bpf_hw_output_report - Send an output report to a HID device
467 *
468 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
469 * @buf: a %PTR_TO_MEM buffer
470 * @buf__sz: the size of the data to transfer
471 *
472 * Returns the number of bytes transferred on success, a negative error code otherwise.
473 */
474 __bpf_kfunc int
hid_bpf_hw_output_report(struct hid_bpf_ctx * ctx,__u8 * buf,size_t buf__sz)475 hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz)
476 {
477 struct hid_bpf_ctx_kern *ctx_kern;
478 size_t size = buf__sz;
479 u8 *dma_data;
480 int ret;
481
482 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
483 if (ctx_kern->from_bpf)
484 return -EDEADLOCK;
485
486 /* check arguments */
487 ret = __hid_bpf_hw_check_params(ctx, buf, &size, HID_OUTPUT_REPORT, true);
488 if (ret)
489 return ret;
490
491 dma_data = kmemdup(buf, size, GFP_KERNEL);
492 if (!dma_data)
493 return -ENOMEM;
494
495 ret = hid_ops->hid_hw_output_report(ctx->hid, dma_data, size, (u64)(long)ctx, true);
496
497 kfree(dma_data);
498 return ret;
499 }
500
501 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)502 __hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
503 size_t size, bool lock_already_taken)
504 {
505 struct hid_bpf_ctx_kern *ctx_kern;
506 int ret;
507
508 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
509 if (ctx_kern->from_bpf)
510 return -EDEADLOCK;
511
512 /* check arguments */
513 ret = __hid_bpf_hw_check_params(ctx, buf, &size, type, false);
514 if (ret)
515 return ret;
516
517 return hid_ops->hid_input_report(ctx->hid, type, buf, size, size, 0, (u64)(long)ctx, true,
518 lock_already_taken);
519 }
520
521 /**
522 * hid_bpf_try_input_report - Inject a HID report in the kernel from a HID device
523 *
524 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
525 * @type: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
526 * @buf: a %PTR_TO_MEM buffer
527 * @buf__sz: the size of the data to transfer
528 *
529 * Returns %0 on success, a negative error code otherwise. This function will immediately
530 * fail if the device is not available, thus can be safely used in IRQ context.
531 */
532 __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)533 hid_bpf_try_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
534 const size_t buf__sz)
535 {
536 struct hid_bpf_ctx_kern *ctx_kern;
537 bool from_hid_event_hook;
538
539 ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
540 from_hid_event_hook = ctx_kern->data && ctx_kern->data == ctx->hid->bpf.device_data;
541
542 return __hid_bpf_input_report(ctx, type, buf, buf__sz, from_hid_event_hook);
543 }
544
545 /**
546 * hid_bpf_input_report - Inject a HID report in the kernel from a HID device
547 *
548 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
549 * @type: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
550 * @buf: a %PTR_TO_MEM buffer
551 * @buf__sz: the size of the data to transfer
552 *
553 * Returns %0 on success, a negative error code otherwise. This function will wait for the
554 * device to be available before injecting the event, thus needs to be called in sleepable
555 * context.
556 */
557 __bpf_kfunc int
hid_bpf_input_report(struct hid_bpf_ctx * ctx,enum hid_report_type type,u8 * buf,const size_t buf__sz)558 hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
559 const size_t buf__sz)
560 {
561 int ret;
562
563 ret = down_interruptible(&ctx->hid->driver_input_lock);
564 if (ret)
565 return ret;
566
567 /* check arguments */
568 ret = __hid_bpf_input_report(ctx, type, buf, buf__sz, true /* lock_already_taken */);
569
570 up(&ctx->hid->driver_input_lock);
571
572 return ret;
573 }
574 __bpf_kfunc_end_defs();
575
576 /*
577 * The following set contains all functions we agree BPF programs
578 * can use.
579 */
580 BTF_KFUNCS_START(hid_bpf_kfunc_ids)
581 BTF_ID_FLAGS(func, hid_bpf_get_data, KF_RET_NULL)
582 BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
583 BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE | KF_SLEEPABLE)
584 BTF_ID_FLAGS(func, hid_bpf_hw_request, KF_SLEEPABLE)
585 BTF_ID_FLAGS(func, hid_bpf_hw_output_report, KF_SLEEPABLE)
586 BTF_ID_FLAGS(func, hid_bpf_input_report, KF_SLEEPABLE)
587 BTF_ID_FLAGS(func, hid_bpf_try_input_report)
588 BTF_KFUNCS_END(hid_bpf_kfunc_ids)
589
590 static const struct btf_kfunc_id_set hid_bpf_kfunc_set = {
591 .owner = THIS_MODULE,
592 .set = &hid_bpf_kfunc_ids,
593 };
594
595 /* for syscall HID-BPF */
596 BTF_KFUNCS_START(hid_bpf_syscall_kfunc_ids)
597 BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
598 BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE | KF_SLEEPABLE)
599 BTF_ID_FLAGS(func, hid_bpf_hw_request, KF_SLEEPABLE)
600 BTF_ID_FLAGS(func, hid_bpf_hw_output_report, KF_SLEEPABLE)
601 BTF_ID_FLAGS(func, hid_bpf_input_report, KF_SLEEPABLE)
602 BTF_KFUNCS_END(hid_bpf_syscall_kfunc_ids)
603
604 static const struct btf_kfunc_id_set hid_bpf_syscall_kfunc_set = {
605 .owner = THIS_MODULE,
606 .set = &hid_bpf_syscall_kfunc_ids,
607 };
608
hid_bpf_connect_device(struct hid_device * hdev)609 int hid_bpf_connect_device(struct hid_device *hdev)
610 {
611 bool need_to_allocate = false;
612 struct hid_bpf_ops *e;
613
614 rcu_read_lock();
615 list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
616 if (e->hid_device_event) {
617 need_to_allocate = true;
618 break;
619 }
620 }
621 rcu_read_unlock();
622
623 /* only allocate BPF data if there are programs attached */
624 if (!need_to_allocate)
625 return 0;
626
627 return hid_bpf_allocate_event_data(hdev);
628 }
629 EXPORT_SYMBOL_GPL(hid_bpf_connect_device);
630
hid_bpf_disconnect_device(struct hid_device * hdev)631 void hid_bpf_disconnect_device(struct hid_device *hdev)
632 {
633 kfree(hdev->bpf.device_data);
634 hdev->bpf.device_data = NULL;
635 hdev->bpf.allocated_data = 0;
636 }
637 EXPORT_SYMBOL_GPL(hid_bpf_disconnect_device);
638
hid_bpf_destroy_device(struct hid_device * hdev)639 void hid_bpf_destroy_device(struct hid_device *hdev)
640 {
641 if (!hdev)
642 return;
643
644 /* mark the device as destroyed in bpf so we don't reattach it */
645 hdev->bpf.destroyed = true;
646
647 __hid_bpf_ops_destroy_device(hdev);
648
649 synchronize_srcu(&hdev->bpf.srcu);
650 cleanup_srcu_struct(&hdev->bpf.srcu);
651 }
652 EXPORT_SYMBOL_GPL(hid_bpf_destroy_device);
653
hid_bpf_device_init(struct hid_device * hdev)654 int hid_bpf_device_init(struct hid_device *hdev)
655 {
656 INIT_LIST_HEAD(&hdev->bpf.prog_list);
657 mutex_init(&hdev->bpf.prog_list_lock);
658 return init_srcu_struct(&hdev->bpf.srcu);
659 }
660 EXPORT_SYMBOL_GPL(hid_bpf_device_init);
661
hid_bpf_init(void)662 static int __init hid_bpf_init(void)
663 {
664 int err;
665
666 /* Note: if we exit with an error any time here, we would entirely break HID, which
667 * is probably not something we want. So we log an error and return success.
668 *
669 * This is not a big deal: nobody will be able to use the functionality.
670 */
671
672 err = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &hid_bpf_kfunc_set);
673 if (err) {
674 pr_warn("error while setting HID BPF tracing kfuncs: %d", err);
675 return 0;
676 }
677
678 err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set);
679 if (err) {
680 pr_warn("error while setting HID BPF syscall kfuncs: %d", err);
681 return 0;
682 }
683
684 return 0;
685 }
686
687 late_initcall(hid_bpf_init);
688 MODULE_AUTHOR("Benjamin Tissoires");
689 MODULE_LICENSE("GPL");
690