Commit | Line | Data |
---|---|---|
f5c27da4 BT |
1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
2 | ||
3 | #ifndef __HID_BPF_H | |
4 | #define __HID_BPF_H | |
5 | ||
4b9a3f49 | 6 | #include <linux/bpf.h> |
f5c27da4 BT |
7 | #include <linux/spinlock.h> |
8 | #include <uapi/linux/hid.h> | |
9 | ||
10 | struct hid_device; | |
11 | ||
12 | /* | |
13 | * The following is the user facing HID BPF API. | |
14 | * | |
15 | * Extra care should be taken when editing this part, as | |
16 | * it might break existing out of the tree bpf programs. | |
17 | */ | |
18 | ||
19 | /** | |
20 | * struct hid_bpf_ctx - User accessible data for all HID programs | |
21 | * | |
22 | * ``data`` is not directly accessible from the context. We need to issue | |
23 | * a call to ``hid_bpf_get_data()`` in order to get a pointer to that field. | |
24 | * | |
25 | * All of these fields are currently read-only. | |
26 | * | |
27 | * @index: program index in the jump table. No special meaning (a smaller index | |
28 | * doesn't mean the program will be executed before another program with | |
29 | * a bigger index). | |
30 | * @hid: the ``struct hid_device`` representing the device itself | |
31 | * @report_type: used for ``hid_bpf_device_event()`` | |
658ee5a6 BT |
32 | * @allocated_size: Allocated size of data. |
33 | * | |
34 | * This is how much memory is available and can be requested | |
35 | * by the HID program. | |
36 | * Note that for ``HID_BPF_RDESC_FIXUP``, that memory is set to | |
37 | * ``4096`` (4 KB) | |
f5c27da4 BT |
38 | * @size: Valid data in the data field. |
39 | * | |
40 | * Programs can get the available valid size in data by fetching this field. | |
658ee5a6 BT |
41 | * Programs can also change this value by returning a positive number in the |
42 | * program. | |
43 | * To discard the event, return a negative error code. | |
44 | * | |
45 | * ``size`` must always be less or equal than ``allocated_size`` (it is enforced | |
46 | * once all BPF programs have been run). | |
47 | * @retval: Return value of the previous program. | |
f5c27da4 BT |
48 | */ |
49 | struct hid_bpf_ctx { | |
50 | __u32 index; | |
51 | const struct hid_device *hid; | |
658ee5a6 | 52 | __u32 allocated_size; |
f5c27da4 | 53 | enum hid_report_type report_type; |
658ee5a6 BT |
54 | union { |
55 | __s32 retval; | |
56 | __s32 size; | |
57 | }; | |
f5c27da4 BT |
58 | }; |
59 | ||
60 | /** | |
61 | * enum hid_bpf_attach_flags - flags used when attaching a HIF-BPF program | |
62 | * | |
63 | * @HID_BPF_FLAG_NONE: no specific flag is used, the kernel choses where to | |
64 | * insert the program | |
65 | * @HID_BPF_FLAG_INSERT_HEAD: insert the given program before any other program | |
66 | * currently attached to the device. This doesn't | |
67 | * guarantee that this program will always be first | |
68 | * @HID_BPF_FLAG_MAX: sentinel value, not to be used by the callers | |
69 | */ | |
70 | enum hid_bpf_attach_flags { | |
71 | HID_BPF_FLAG_NONE = 0, | |
72 | HID_BPF_FLAG_INSERT_HEAD = _BITUL(0), | |
73 | HID_BPF_FLAG_MAX, | |
74 | }; | |
75 | ||
76 | /* Following functions are tracepoints that BPF programs can attach to */ | |
77 | int hid_bpf_device_event(struct hid_bpf_ctx *ctx); | |
ad190df1 | 78 | int hid_bpf_rdesc_fixup(struct hid_bpf_ctx *ctx); |
f5c27da4 | 79 | |
f5c27da4 BT |
80 | /* |
81 | * Below is HID internal | |
82 | */ | |
83 | ||
84 | /* internal function to call eBPF programs, not to be used by anybody */ | |
85 | int __hid_bpf_tail_call(struct hid_bpf_ctx *ctx); | |
86 | ||
87 | #define HID_BPF_MAX_PROGS_PER_DEV 64 | |
88 | #define HID_BPF_FLAG_MASK (((HID_BPF_FLAG_MAX - 1) << 1) - 1) | |
89 | ||
90 | /* types of HID programs to attach to */ | |
91 | enum hid_bpf_prog_type { | |
92 | HID_BPF_PROG_TYPE_UNDEF = -1, | |
93 | HID_BPF_PROG_TYPE_DEVICE_EVENT, /* an event is emitted from the device */ | |
ad190df1 | 94 | HID_BPF_PROG_TYPE_RDESC_FIXUP, |
f5c27da4 BT |
95 | HID_BPF_PROG_TYPE_MAX, |
96 | }; | |
97 | ||
91a7f802 BT |
98 | struct hid_report_enum; |
99 | ||
f5c27da4 | 100 | struct hid_bpf_ops { |
91a7f802 BT |
101 | struct hid_report *(*hid_get_report)(struct hid_report_enum *report_enum, const u8 *data); |
102 | int (*hid_hw_raw_request)(struct hid_device *hdev, | |
103 | unsigned char reportnum, __u8 *buf, | |
104 | size_t len, enum hid_report_type rtype, | |
105 | enum hid_class_request reqtype); | |
f5c27da4 | 106 | struct module *owner; |
9b0a3839 | 107 | const struct bus_type *bus_type; |
f5c27da4 BT |
108 | }; |
109 | ||
110 | extern struct hid_bpf_ops *hid_bpf_ops; | |
111 | ||
112 | struct hid_bpf_prog_list { | |
113 | u16 prog_idx[HID_BPF_MAX_PROGS_PER_DEV]; | |
114 | u8 prog_cnt; | |
115 | }; | |
116 | ||
117 | /* stored in each device */ | |
118 | struct hid_bpf { | |
658ee5a6 BT |
119 | u8 *device_data; /* allocated when a bpf program of type |
120 | * SEC(f.../hid_bpf_device_event) has been attached | |
121 | * to this HID device | |
122 | */ | |
123 | u32 allocated_data; | |
124 | ||
f5c27da4 BT |
125 | struct hid_bpf_prog_list __rcu *progs[HID_BPF_PROG_TYPE_MAX]; /* attached BPF progs */ |
126 | bool destroyed; /* prevents the assignment of any progs */ | |
127 | ||
128 | spinlock_t progs_lock; /* protects RCU update of progs */ | |
129 | }; | |
130 | ||
4b9a3f49 BT |
131 | /* specific HID-BPF link when a program is attached to a device */ |
132 | struct hid_bpf_link { | |
133 | struct bpf_link link; | |
134 | int hid_table_index; | |
135 | }; | |
136 | ||
f5c27da4 | 137 | #ifdef CONFIG_HID_BPF |
658ee5a6 BT |
138 | u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, u8 *data, |
139 | u32 *size, int interrupt); | |
140 | int hid_bpf_connect_device(struct hid_device *hdev); | |
141 | void hid_bpf_disconnect_device(struct hid_device *hdev); | |
f5c27da4 BT |
142 | void hid_bpf_destroy_device(struct hid_device *hid); |
143 | void hid_bpf_device_init(struct hid_device *hid); | |
ad190df1 | 144 | u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size); |
f5c27da4 | 145 | #else /* CONFIG_HID_BPF */ |
658ee5a6 | 146 | static inline u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, |
576e619b | 147 | u8 *data, u32 *size, int interrupt) { return data; } |
658ee5a6 BT |
148 | static inline int hid_bpf_connect_device(struct hid_device *hdev) { return 0; } |
149 | static inline void hid_bpf_disconnect_device(struct hid_device *hdev) {} | |
f5c27da4 BT |
150 | static inline void hid_bpf_destroy_device(struct hid_device *hid) {} |
151 | static inline void hid_bpf_device_init(struct hid_device *hid) {} | |
ad190df1 BT |
152 | static inline u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size) |
153 | { | |
154 | return kmemdup(rdesc, *size, GFP_KERNEL); | |
155 | } | |
156 | ||
f5c27da4 BT |
157 | #endif /* CONFIG_HID_BPF */ |
158 | ||
159 | #endif /* __HID_BPF_H */ |