• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 (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 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 kmemdup(rdesc, *size, GFP_KERNEL);
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 		return device_reprobe(&hdev->dev);
274 
275 	return 0;
276 }
277 
278 /* Disables missing prototype warnings */
279 __bpf_kfunc_start_defs();
280 
281 /**
282  * hid_bpf_get_data - Get the kernel memory pointer associated with the context @ctx
283  *
284  * @ctx: The HID-BPF context
285  * @offset: The offset within the memory
286  * @rdwr_buf_size: the const size of the buffer
287  *
288  * @returns %NULL on error, an %__u8 memory pointer on success
289  */
290 __bpf_kfunc __u8 *
hid_bpf_get_data(struct hid_bpf_ctx * ctx,unsigned int offset,const size_t rdwr_buf_size)291 hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr_buf_size)
292 {
293 	struct hid_bpf_ctx_kern *ctx_kern;
294 
295 	if (!ctx)
296 		return NULL;
297 
298 	ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
299 
300 	if (rdwr_buf_size + offset > ctx->allocated_size)
301 		return NULL;
302 
303 	return ctx_kern->data + offset;
304 }
305 
306 /**
307  * hid_bpf_allocate_context - Allocate a context to the given HID device
308  *
309  * @hid_id: the system unique identifier of the HID device
310  *
311  * @returns A pointer to &struct hid_bpf_ctx on success, %NULL on error.
312  */
313 __bpf_kfunc struct hid_bpf_ctx *
hid_bpf_allocate_context(unsigned int hid_id)314 hid_bpf_allocate_context(unsigned int hid_id)
315 {
316 	struct hid_device *hdev;
317 	struct hid_bpf_ctx_kern *ctx_kern = NULL;
318 
319 	hdev = hid_get_device(hid_id);
320 	if (IS_ERR(hdev))
321 		return NULL;
322 
323 	ctx_kern = kzalloc(sizeof(*ctx_kern), GFP_KERNEL);
324 	if (!ctx_kern) {
325 		hid_put_device(hdev);
326 		return NULL;
327 	}
328 
329 	ctx_kern->ctx.hid = hdev;
330 
331 	return &ctx_kern->ctx;
332 }
333 
334 /**
335  * hid_bpf_release_context - Release the previously allocated context @ctx
336  *
337  * @ctx: the HID-BPF context to release
338  *
339  */
340 __bpf_kfunc void
hid_bpf_release_context(struct hid_bpf_ctx * ctx)341 hid_bpf_release_context(struct hid_bpf_ctx *ctx)
342 {
343 	struct hid_bpf_ctx_kern *ctx_kern;
344 	struct hid_device *hid;
345 
346 	ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
347 	hid = (struct hid_device *)ctx_kern->ctx.hid; /* ignore const */
348 
349 	kfree(ctx_kern);
350 
351 	/* get_device() is called by bus_find_device() */
352 	hid_put_device(hid);
353 }
354 
355 static int
__hid_bpf_hw_check_params(struct hid_bpf_ctx * ctx,__u8 * buf,size_t * buf__sz,enum hid_report_type rtype)356 __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz,
357 			  enum hid_report_type rtype)
358 {
359 	struct hid_report_enum *report_enum;
360 	struct hid_report *report;
361 	struct hid_device *hdev;
362 	u32 report_len;
363 
364 	/* check arguments */
365 	if (!ctx || !hid_ops || !buf)
366 		return -EINVAL;
367 
368 	switch (rtype) {
369 	case HID_INPUT_REPORT:
370 	case HID_OUTPUT_REPORT:
371 	case HID_FEATURE_REPORT:
372 		break;
373 	default:
374 		return -EINVAL;
375 	}
376 
377 	if (*buf__sz < 1)
378 		return -EINVAL;
379 
380 	hdev = (struct hid_device *)ctx->hid; /* discard const */
381 
382 	report_enum = hdev->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 	struct hid_device *hdev;
412 	size_t size = buf__sz;
413 	u8 *dma_data;
414 	int ret;
415 
416 	ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
417 
418 	if (ctx_kern->from_bpf)
419 		return -EDEADLOCK;
420 
421 	/* check arguments */
422 	ret = __hid_bpf_hw_check_params(ctx, buf, &size, rtype);
423 	if (ret)
424 		return ret;
425 
426 	switch (reqtype) {
427 	case HID_REQ_GET_REPORT:
428 	case HID_REQ_GET_IDLE:
429 	case HID_REQ_GET_PROTOCOL:
430 	case HID_REQ_SET_REPORT:
431 	case HID_REQ_SET_IDLE:
432 	case HID_REQ_SET_PROTOCOL:
433 		break;
434 	default:
435 		return -EINVAL;
436 	}
437 
438 	hdev = (struct hid_device *)ctx->hid; /* discard const */
439 
440 	dma_data = kmemdup(buf, size, GFP_KERNEL);
441 	if (!dma_data)
442 		return -ENOMEM;
443 
444 	ret = hid_ops->hid_hw_raw_request(hdev,
445 					      dma_data[0],
446 					      dma_data,
447 					      size,
448 					      rtype,
449 					      reqtype,
450 					      (u64)(long)ctx,
451 					      true); /* prevent infinite recursions */
452 
453 	if (ret > 0)
454 		memcpy(buf, dma_data, ret);
455 
456 	kfree(dma_data);
457 	return ret;
458 }
459 
460 /**
461  * hid_bpf_hw_output_report - Send an output report to a HID device
462  *
463  * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
464  * @buf: a %PTR_TO_MEM buffer
465  * @buf__sz: the size of the data to transfer
466  *
467  * Returns the number of bytes transferred on success, a negative error code otherwise.
468  */
469 __bpf_kfunc int
hid_bpf_hw_output_report(struct hid_bpf_ctx * ctx,__u8 * buf,size_t buf__sz)470 hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz)
471 {
472 	struct hid_bpf_ctx_kern *ctx_kern;
473 	struct hid_device *hdev;
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 	hdev = (struct hid_device *)ctx->hid; /* discard const */
488 
489 	dma_data = kmemdup(buf, size, GFP_KERNEL);
490 	if (!dma_data)
491 		return -ENOMEM;
492 
493 	ret = hid_ops->hid_hw_output_report(hdev, dma_data, size, (u64)(long)ctx, true);
494 
495 	kfree(dma_data);
496 	return ret;
497 }
498 
499 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)500 __hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
501 		       size_t size, bool lock_already_taken)
502 {
503 	struct hid_bpf_ctx_kern *ctx_kern;
504 	int ret;
505 
506 	ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
507 	if (ctx_kern->from_bpf)
508 		return -EDEADLOCK;
509 
510 	/* check arguments */
511 	ret = __hid_bpf_hw_check_params(ctx, buf, &size, type);
512 	if (ret)
513 		return ret;
514 
515 	return hid_ops->hid_input_report(ctx->hid, type, buf, size, 0, (u64)(long)ctx, true,
516 					 lock_already_taken);
517 }
518 
519 /**
520  * hid_bpf_try_input_report - Inject a HID report in the kernel from a HID device
521  *
522  * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
523  * @type: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
524  * @buf: a %PTR_TO_MEM buffer
525  * @buf__sz: the size of the data to transfer
526  *
527  * Returns %0 on success, a negative error code otherwise. This function will immediately
528  * fail if the device is not available, thus can be safely used in IRQ context.
529  */
530 __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)531 hid_bpf_try_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
532 			 const size_t buf__sz)
533 {
534 	struct hid_bpf_ctx_kern *ctx_kern;
535 	bool from_hid_event_hook;
536 
537 	ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
538 	from_hid_event_hook = ctx_kern->data && ctx_kern->data == ctx->hid->bpf.device_data;
539 
540 	return __hid_bpf_input_report(ctx, type, buf, buf__sz, from_hid_event_hook);
541 }
542 
543 /**
544  * hid_bpf_input_report - Inject a HID report in the kernel from a HID device
545  *
546  * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
547  * @type: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
548  * @buf: a %PTR_TO_MEM buffer
549  * @buf__sz: the size of the data to transfer
550  *
551  * Returns %0 on success, a negative error code otherwise. This function will wait for the
552  * device to be available before injecting the event, thus needs to be called in sleepable
553  * context.
554  */
555 __bpf_kfunc int
hid_bpf_input_report(struct hid_bpf_ctx * ctx,enum hid_report_type type,u8 * buf,const size_t buf__sz)556 hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf,
557 		     const size_t buf__sz)
558 {
559 	int ret;
560 
561 	ret = down_interruptible(&ctx->hid->driver_input_lock);
562 	if (ret)
563 		return ret;
564 
565 	/* check arguments */
566 	ret = __hid_bpf_input_report(ctx, type, buf, buf__sz, true /* lock_already_taken */);
567 
568 	up(&ctx->hid->driver_input_lock);
569 
570 	return ret;
571 }
572 __bpf_kfunc_end_defs();
573 
574 /*
575  * The following set contains all functions we agree BPF programs
576  * can use.
577  */
578 BTF_KFUNCS_START(hid_bpf_kfunc_ids)
579 BTF_ID_FLAGS(func, hid_bpf_get_data, KF_RET_NULL)
580 BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)
581 BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE | KF_SLEEPABLE)
582 BTF_ID_FLAGS(func, hid_bpf_hw_request, KF_SLEEPABLE)
583 BTF_ID_FLAGS(func, hid_bpf_hw_output_report, KF_SLEEPABLE)
584 BTF_ID_FLAGS(func, hid_bpf_input_report, KF_SLEEPABLE)
585 BTF_ID_FLAGS(func, hid_bpf_try_input_report)
586 BTF_KFUNCS_END(hid_bpf_kfunc_ids)
587 
588 static const struct btf_kfunc_id_set hid_bpf_kfunc_set = {
589 	.owner = THIS_MODULE,
590 	.set   = &hid_bpf_kfunc_ids,
591 };
592 
593 /* for syscall HID-BPF */
594 BTF_KFUNCS_START(hid_bpf_syscall_kfunc_ids)
595 BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL)
596 BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE)
597 BTF_ID_FLAGS(func, hid_bpf_hw_request)
598 BTF_ID_FLAGS(func, hid_bpf_hw_output_report)
599 BTF_ID_FLAGS(func, hid_bpf_input_report)
600 BTF_KFUNCS_END(hid_bpf_syscall_kfunc_ids)
601 
602 static const struct btf_kfunc_id_set hid_bpf_syscall_kfunc_set = {
603 	.owner = THIS_MODULE,
604 	.set   = &hid_bpf_syscall_kfunc_ids,
605 };
606 
hid_bpf_connect_device(struct hid_device * hdev)607 int hid_bpf_connect_device(struct hid_device *hdev)
608 {
609 	bool need_to_allocate = false;
610 	struct hid_bpf_ops *e;
611 
612 	rcu_read_lock();
613 	list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
614 		if (e->hid_device_event) {
615 			need_to_allocate = true;
616 			break;
617 		}
618 	}
619 	rcu_read_unlock();
620 
621 	/* only allocate BPF data if there are programs attached */
622 	if (!need_to_allocate)
623 		return 0;
624 
625 	return hid_bpf_allocate_event_data(hdev);
626 }
627 EXPORT_SYMBOL_GPL(hid_bpf_connect_device);
628 
hid_bpf_disconnect_device(struct hid_device * hdev)629 void hid_bpf_disconnect_device(struct hid_device *hdev)
630 {
631 	kfree(hdev->bpf.device_data);
632 	hdev->bpf.device_data = NULL;
633 	hdev->bpf.allocated_data = 0;
634 }
635 EXPORT_SYMBOL_GPL(hid_bpf_disconnect_device);
636 
hid_bpf_destroy_device(struct hid_device * hdev)637 void hid_bpf_destroy_device(struct hid_device *hdev)
638 {
639 	if (!hdev)
640 		return;
641 
642 	/* mark the device as destroyed in bpf so we don't reattach it */
643 	hdev->bpf.destroyed = true;
644 
645 	__hid_bpf_ops_destroy_device(hdev);
646 
647 	synchronize_srcu(&hdev->bpf.srcu);
648 	cleanup_srcu_struct(&hdev->bpf.srcu);
649 }
650 EXPORT_SYMBOL_GPL(hid_bpf_destroy_device);
651 
hid_bpf_device_init(struct hid_device * hdev)652 int hid_bpf_device_init(struct hid_device *hdev)
653 {
654 	INIT_LIST_HEAD(&hdev->bpf.prog_list);
655 	mutex_init(&hdev->bpf.prog_list_lock);
656 	return init_srcu_struct(&hdev->bpf.srcu);
657 }
658 EXPORT_SYMBOL_GPL(hid_bpf_device_init);
659 
hid_bpf_init(void)660 static int __init hid_bpf_init(void)
661 {
662 	int err;
663 
664 	/* Note: if we exit with an error any time here, we would entirely break HID, which
665 	 * is probably not something we want. So we log an error and return success.
666 	 *
667 	 * This is not a big deal: nobody will be able to use the functionality.
668 	 */
669 
670 	err = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &hid_bpf_kfunc_set);
671 	if (err) {
672 		pr_warn("error while setting HID BPF tracing kfuncs: %d", err);
673 		return 0;
674 	}
675 
676 	err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set);
677 	if (err) {
678 		pr_warn("error while setting HID BPF syscall kfuncs: %d", err);
679 		return 0;
680 	}
681 
682 	return 0;
683 }
684 
685 late_initcall(hid_bpf_init);
686 MODULE_AUTHOR("Benjamin Tissoires");
687 MODULE_LICENSE("GPL");
688