1// SPDX-License-Identifier: GPL-2.0-only
2
3/*
4 *  HID-BPF support for Linux
5 *
6 *  Copyright (c) 2022 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/workqueue.h>
21#include "hid_bpf_dispatch.h"
22#include "entrypoints/entrypoints.lskel.h"
23
24struct hid_bpf_ops *hid_bpf_ops;
25EXPORT_SYMBOL(hid_bpf_ops);
26
27/**
28 * hid_bpf_device_event - Called whenever an event is coming in from the device
29 *
30 * @ctx: The HID-BPF context
31 *
32 * @return %0 on success and keep processing; a positive value to change the
33 * incoming size buffer; a negative error code to interrupt the processing
34 * of this event
35 *
36 * Declare an %fmod_ret tracing bpf program to this function and attach this
37 * program through hid_bpf_attach_prog() to have this helper called for
38 * any incoming event from the device itself.
39 *
40 * The function is called while on IRQ context, so we can not sleep.
41 */
42/* never used by the kernel but declared so we can load and attach a tracepoint */
43__weak noinline int hid_bpf_device_event(struct hid_bpf_ctx *ctx)
44{
45	return 0;
46}
47
48u8 *
49dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data,
50			      u32 *size, int interrupt)
51{
52	struct hid_bpf_ctx_kern ctx_kern = {
53		.ctx = {
54			.hid = hdev,
55			.report_type = type,
56			.allocated_size = hdev->bpf.allocated_data,
57			.size = *size,
58		},
59		.data = hdev->bpf.device_data,
60	};
61	int ret;
62
63	if (type >= HID_REPORT_TYPES)
64		return ERR_PTR(-EINVAL);
65
66	/* no program has been attached yet */
67	if (!hdev->bpf.device_data)
68		return data;
69
70	memset(ctx_kern.data, 0, hdev->bpf.allocated_data);
71	memcpy(ctx_kern.data, data, *size);
72
73	ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_DEVICE_EVENT, &ctx_kern);
74	if (ret < 0)
75		return ERR_PTR(ret);
76
77	if (ret) {
78		if (ret > ctx_kern.ctx.allocated_size)
79			return ERR_PTR(-EINVAL);
80
81		*size = ret;
82	}
83
84	return ctx_kern.data;
85}
86EXPORT_SYMBOL_GPL(dispatch_hid_bpf_device_event);
87
88/**
89 * hid_bpf_rdesc_fixup - Called when the probe function parses the report
90 * descriptor of the HID device
91 *
92 * @ctx: The HID-BPF context
93 *
94 * @return 0 on success and keep processing; a positive value to change the
95 * incoming size buffer; a negative error code to interrupt the processing
96 * of this event
97 *
98 * Declare an %fmod_ret tracing bpf program to this function and attach this
99 * program through hid_bpf_attach_prog() to have this helper called before any
100 * parsing of the report descriptor by HID.
101 */
102/* never used by the kernel but declared so we can load and attach a tracepoint */
103__weak noinline int hid_bpf_rdesc_fixup(struct hid_bpf_ctx *ctx)
104{
105	return 0;
106}
107
108u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size)
109{
110	int ret;
111	struct hid_bpf_ctx_kern ctx_kern = {
112		.ctx = {
113			.hid = hdev,
114			.size = *size,
115			.allocated_size = HID_MAX_DESCRIPTOR_SIZE,
116		},
117	};
118
119	ctx_kern.data = kzalloc(ctx_kern.ctx.allocated_size, GFP_KERNEL);
120	if (!ctx_kern.data)
121		goto ignore_bpf;
122
123	memcpy(ctx_kern.data, rdesc, min_t(unsigned int, *size, HID_MAX_DESCRIPTOR_SIZE));
124
125	ret = hid_bpf_prog_run(hdev, HID_BPF_PROG_TYPE_RDESC_FIXUP, &ctx_kern);
126	if (ret < 0)
127		goto ignore_bpf;
128
129	if (ret) {
130		if (ret > ctx_kern.ctx.allocated_size)
131			goto ignore_bpf;
132
133		*size = ret;
134	}
135
136	rdesc = krealloc(ctx_kern.data, *size, GFP_KERNEL);
137
138	return rdesc;
139
140 ignore_bpf:
141	kfree(ctx_kern.data);
142	return kmemdup(rdesc, *size, GFP_KERNEL);
143}
144EXPORT_SYMBOL_GPL(call_hid_bpf_rdesc_fixup);
145
146/**
147 * hid_bpf_get_data - Get the kernel memory pointer associated with the context @ctx
148 *
149 * @ctx: The HID-BPF context
150 * @offset: The offset within the memory
151 * @rdwr_buf_size: the const size of the buffer
152 *
153 * @returns %NULL on error, an %__u8 memory pointer on success
154 */
155noinline __u8 *
156hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr_buf_size)
157{
158	struct hid_bpf_ctx_kern *ctx_kern;
159
160	if (!ctx)
161		return NULL;
162
163	ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
164
165	if (rdwr_buf_size + offset > ctx->allocated_size)
166		return NULL;
167
168	return ctx_kern->data + offset;
169}
170
171/*
172 * The following set contains all functions we agree BPF programs
173 * can use.
174 */
175BTF_SET8_START(hid_bpf_kfunc_ids)
176BTF_ID_FLAGS(func, hid_bpf_get_data, KF_RET_NULL)
177BTF_SET8_END(hid_bpf_kfunc_ids)
178
179static const struct btf_kfunc_id_set hid_bpf_kfunc_set = {
180	.owner = THIS_MODULE,
181	.set   = &hid_bpf_kfunc_ids,
182};
183
184static int device_match_id(struct device *dev, const void *id)
185{
186	struct hid_device *hdev = to_hid_device(dev);
187
188	return hdev->id == *(int *)id;
189}
190
191static int __hid_bpf_allocate_data(struct hid_device *hdev, u8 **data, u32 *size)
192{
193	u8 *alloc_data;
194	unsigned int i, j, max_report_len = 0;
195	size_t alloc_size = 0;
196
197	/* compute the maximum report length for this device */
198	for (i = 0; i < HID_REPORT_TYPES; i++) {
199		struct hid_report_enum *report_enum = hdev->report_enum + i;
200
201		for (j = 0; j < HID_MAX_IDS; j++) {
202			struct hid_report *report = report_enum->report_id_hash[j];
203
204			if (report)
205				max_report_len = max(max_report_len, hid_report_len(report));
206		}
207	}
208
209	/*
210	 * Give us a little bit of extra space and some predictability in the
211	 * buffer length we create. This way, we can tell users that they can
212	 * work on chunks of 64 bytes of memory without having the bpf verifier
213	 * scream at them.
214	 */
215	alloc_size = DIV_ROUND_UP(max_report_len, 64) * 64;
216
217	alloc_data = kzalloc(alloc_size, GFP_KERNEL);
218	if (!alloc_data)
219		return -ENOMEM;
220
221	*data = alloc_data;
222	*size = alloc_size;
223
224	return 0;
225}
226
227static int hid_bpf_allocate_event_data(struct hid_device *hdev)
228{
229	/* hdev->bpf.device_data is already allocated, abort */
230	if (hdev->bpf.device_data)
231		return 0;
232
233	return __hid_bpf_allocate_data(hdev, &hdev->bpf.device_data, &hdev->bpf.allocated_data);
234}
235
236int hid_bpf_reconnect(struct hid_device *hdev)
237{
238	if (!test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status))
239		return device_reprobe(&hdev->dev);
240
241	return 0;
242}
243
244static int do_hid_bpf_attach_prog(struct hid_device *hdev, int prog_fd, struct bpf_prog *prog,
245				  __u32 flags)
246{
247	int fd, err, prog_type;
248
249	prog_type = hid_bpf_get_prog_attach_type(prog);
250	if (prog_type < 0)
251		return prog_type;
252
253	if (prog_type >= HID_BPF_PROG_TYPE_MAX)
254		return -EINVAL;
255
256	if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) {
257		err = hid_bpf_allocate_event_data(hdev);
258		if (err)
259			return err;
260	}
261
262	fd = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, prog, flags);
263	if (fd < 0)
264		return fd;
265
266	if (prog_type == HID_BPF_PROG_TYPE_RDESC_FIXUP) {
267		err = hid_bpf_reconnect(hdev);
268		if (err) {
269			close_fd(fd);
270			return err;
271		}
272	}
273
274	return fd;
275}
276
277/**
278 * hid_bpf_attach_prog - Attach the given @prog_fd to the given HID device
279 *
280 * @hid_id: the system unique identifier of the HID device
281 * @prog_fd: an fd in the user process representing the program to attach
282 * @flags: any logical OR combination of &enum hid_bpf_attach_flags
283 *
284 * @returns an fd of a bpf_link object on success (> %0), an error code otherwise.
285 * Closing this fd will detach the program from the HID device (unless the bpf_link
286 * is pinned to the BPF file system).
287 */
288/* called from syscall */
289noinline int
290hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
291{
292	struct hid_device *hdev;
293	struct bpf_prog *prog;
294	struct device *dev;
295	int err, fd;
296
297	if (!hid_bpf_ops)
298		return -EINVAL;
299
300	if ((flags & ~HID_BPF_FLAG_MASK))
301		return -EINVAL;
302
303	dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id);
304	if (!dev)
305		return -EINVAL;
306
307	hdev = to_hid_device(dev);
308
309	/*
310	 * take a ref on the prog itself, it will be released
311	 * on errors or when it'll be detached
312	 */
313	prog = bpf_prog_get(prog_fd);
314	if (IS_ERR(prog)) {
315		err = PTR_ERR(prog);
316		goto out_dev_put;
317	}
318
319	fd = do_hid_bpf_attach_prog(hdev, prog_fd, prog, flags);
320	if (fd < 0) {
321		err = fd;
322		goto out_prog_put;
323	}
324
325	return fd;
326
327 out_prog_put:
328	bpf_prog_put(prog);
329 out_dev_put:
330	put_device(dev);
331	return err;
332}
333
334/**
335 * hid_bpf_allocate_context - Allocate a context to the given HID device
336 *
337 * @hid_id: the system unique identifier of the HID device
338 *
339 * @returns A pointer to &struct hid_bpf_ctx on success, %NULL on error.
340 */
341noinline struct hid_bpf_ctx *
342hid_bpf_allocate_context(unsigned int hid_id)
343{
344	struct hid_device *hdev;
345	struct hid_bpf_ctx_kern *ctx_kern = NULL;
346	struct device *dev;
347
348	if (!hid_bpf_ops)
349		return NULL;
350
351	dev = bus_find_device(hid_bpf_ops->bus_type, NULL, &hid_id, device_match_id);
352	if (!dev)
353		return NULL;
354
355	hdev = to_hid_device(dev);
356
357	ctx_kern = kzalloc(sizeof(*ctx_kern), GFP_KERNEL);
358	if (!ctx_kern) {
359		put_device(dev);
360		return NULL;
361	}
362
363	ctx_kern->ctx.hid = hdev;
364
365	return &ctx_kern->ctx;
366}
367
368/**
369 * hid_bpf_release_context - Release the previously allocated context @ctx
370 *
371 * @ctx: the HID-BPF context to release
372 *
373 */
374noinline void
375hid_bpf_release_context(struct hid_bpf_ctx *ctx)
376{
377	struct hid_bpf_ctx_kern *ctx_kern;
378	struct hid_device *hid;
379
380	ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
381	hid = (struct hid_device *)ctx_kern->ctx.hid; /* ignore const */
382
383	kfree(ctx_kern);
384
385	/* get_device() is called by bus_find_device() */
386	put_device(&hid->dev);
387}
388
389/**
390 * hid_bpf_hw_request - Communicate with a HID device
391 *
392 * @ctx: the HID-BPF context previously allocated in hid_bpf_allocate_context()
393 * @buf: a %PTR_TO_MEM buffer
394 * @buf__sz: the size of the data to transfer
395 * @rtype: the type of the report (%HID_INPUT_REPORT, %HID_FEATURE_REPORT, %HID_OUTPUT_REPORT)
396 * @reqtype: the type of the request (%HID_REQ_GET_REPORT, %HID_REQ_SET_REPORT, ...)
397 *
398 * @returns %0 on success, a negative error code otherwise.
399 */
400noinline int
401hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
402		   enum hid_report_type rtype, enum hid_class_request reqtype)
403{
404	struct hid_device *hdev;
405	struct hid_report *report;
406	struct hid_report_enum *report_enum;
407	u8 *dma_data;
408	u32 report_len;
409	int ret;
410
411	/* check arguments */
412	if (!ctx || !hid_bpf_ops || !buf)
413		return -EINVAL;
414
415	switch (rtype) {
416	case HID_INPUT_REPORT:
417	case HID_OUTPUT_REPORT:
418	case HID_FEATURE_REPORT:
419		break;
420	default:
421		return -EINVAL;
422	}
423
424	switch (reqtype) {
425	case HID_REQ_GET_REPORT:
426	case HID_REQ_GET_IDLE:
427	case HID_REQ_GET_PROTOCOL:
428	case HID_REQ_SET_REPORT:
429	case HID_REQ_SET_IDLE:
430	case HID_REQ_SET_PROTOCOL:
431		break;
432	default:
433		return -EINVAL;
434	}
435
436	if (buf__sz < 1)
437		return -EINVAL;
438
439	hdev = (struct hid_device *)ctx->hid; /* discard const */
440
441	report_enum = hdev->report_enum + rtype;
442	report = hid_bpf_ops->hid_get_report(report_enum, buf);
443	if (!report)
444		return -EINVAL;
445
446	report_len = hid_report_len(report);
447
448	if (buf__sz > report_len)
449		buf__sz = report_len;
450
451	dma_data = kmemdup(buf, buf__sz, GFP_KERNEL);
452	if (!dma_data)
453		return -ENOMEM;
454
455	ret = hid_bpf_ops->hid_hw_raw_request(hdev,
456					      dma_data[0],
457					      dma_data,
458					      buf__sz,
459					      rtype,
460					      reqtype);
461
462	if (ret > 0)
463		memcpy(buf, dma_data, ret);
464
465	kfree(dma_data);
466	return ret;
467}
468
469/* our HID-BPF entrypoints */
470BTF_SET8_START(hid_bpf_fmodret_ids)
471BTF_ID_FLAGS(func, hid_bpf_device_event)
472BTF_ID_FLAGS(func, hid_bpf_rdesc_fixup)
473BTF_ID_FLAGS(func, __hid_bpf_tail_call)
474BTF_SET8_END(hid_bpf_fmodret_ids)
475
476static const struct btf_kfunc_id_set hid_bpf_fmodret_set = {
477	.owner = THIS_MODULE,
478	.set   = &hid_bpf_fmodret_ids,
479};
480
481/* for syscall HID-BPF */
482BTF_SET8_START(hid_bpf_syscall_kfunc_ids)
483BTF_ID_FLAGS(func, hid_bpf_attach_prog)
484BTF_ID_FLAGS(func, hid_bpf_allocate_context, KF_ACQUIRE | KF_RET_NULL)
485BTF_ID_FLAGS(func, hid_bpf_release_context, KF_RELEASE)
486BTF_ID_FLAGS(func, hid_bpf_hw_request)
487BTF_SET8_END(hid_bpf_syscall_kfunc_ids)
488
489static const struct btf_kfunc_id_set hid_bpf_syscall_kfunc_set = {
490	.owner = THIS_MODULE,
491	.set   = &hid_bpf_syscall_kfunc_ids,
492};
493
494int hid_bpf_connect_device(struct hid_device *hdev)
495{
496	struct hid_bpf_prog_list *prog_list;
497
498	rcu_read_lock();
499	prog_list = rcu_dereference(hdev->bpf.progs[HID_BPF_PROG_TYPE_DEVICE_EVENT]);
500	rcu_read_unlock();
501
502	/* only allocate BPF data if there are programs attached */
503	if (!prog_list)
504		return 0;
505
506	return hid_bpf_allocate_event_data(hdev);
507}
508EXPORT_SYMBOL_GPL(hid_bpf_connect_device);
509
510void hid_bpf_disconnect_device(struct hid_device *hdev)
511{
512	kfree(hdev->bpf.device_data);
513	hdev->bpf.device_data = NULL;
514	hdev->bpf.allocated_data = 0;
515}
516EXPORT_SYMBOL_GPL(hid_bpf_disconnect_device);
517
518void hid_bpf_destroy_device(struct hid_device *hdev)
519{
520	if (!hdev)
521		return;
522
523	/* mark the device as destroyed in bpf so we don't reattach it */
524	hdev->bpf.destroyed = true;
525
526	__hid_bpf_destroy_device(hdev);
527}
528EXPORT_SYMBOL_GPL(hid_bpf_destroy_device);
529
530void hid_bpf_device_init(struct hid_device *hdev)
531{
532	spin_lock_init(&hdev->bpf.progs_lock);
533}
534EXPORT_SYMBOL_GPL(hid_bpf_device_init);
535
536static int __init hid_bpf_init(void)
537{
538	int err;
539
540	/* Note: if we exit with an error any time here, we would entirely break HID, which
541	 * is probably not something we want. So we log an error and return success.
542	 *
543	 * This is not a big deal: the syscall allowing to attach a BPF program to a HID device
544	 * will not be available, so nobody will be able to use the functionality.
545	 */
546
547	err = register_btf_fmodret_id_set(&hid_bpf_fmodret_set);
548	if (err) {
549		pr_warn("error while registering fmodret entrypoints: %d", err);
550		return 0;
551	}
552
553	err = hid_bpf_preload_skel();
554	if (err) {
555		pr_warn("error while preloading HID BPF dispatcher: %d", err);
556		return 0;
557	}
558
559	/* register tracing kfuncs after we are sure we can load our preloaded bpf program */
560	err = register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &hid_bpf_kfunc_set);
561	if (err) {
562		pr_warn("error while setting HID BPF tracing kfuncs: %d", err);
563		return 0;
564	}
565
566	/* register syscalls after we are sure we can load our preloaded bpf program */
567	err = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &hid_bpf_syscall_kfunc_set);
568	if (err) {
569		pr_warn("error while setting HID BPF syscall kfuncs: %d", err);
570		return 0;
571	}
572
573	return 0;
574}
575
576static void __exit hid_bpf_exit(void)
577{
578	/* HID depends on us, so if we hit that code, we are guaranteed that hid
579	 * has been removed and thus we do not need to clear the HID devices
580	 */
581	hid_bpf_free_links_and_skel();
582}
583
584late_initcall(hid_bpf_init);
585module_exit(hid_bpf_exit);
586MODULE_AUTHOR("Benjamin Tissoires");
587MODULE_LICENSE("GPL");
588