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