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> |
4a86220e | 7 | #include <linux/mutex.h> |
6cd735f0 | 8 | #include <linux/srcu.h> |
f5c27da4 BT |
9 | #include <uapi/linux/hid.h> |
10 | ||
11 | struct hid_device; | |
12 | ||
13 | /* | |
14 | * The following is the user facing HID BPF API. | |
15 | * | |
16 | * Extra care should be taken when editing this part, as | |
17 | * it might break existing out of the tree bpf programs. | |
18 | */ | |
19 | ||
20 | /** | |
21 | * struct hid_bpf_ctx - User accessible data for all HID programs | |
22 | * | |
23 | * ``data`` is not directly accessible from the context. We need to issue | |
c5958697 | 24 | * a call to hid_bpf_get_data() in order to get a pointer to that field. |
f5c27da4 | 25 | * |
c5958697 | 26 | * @hid: the &struct hid_device representing the device itself |
658ee5a6 BT |
27 | * @allocated_size: Allocated size of data. |
28 | * | |
29 | * This is how much memory is available and can be requested | |
30 | * by the HID program. | |
31 | * Note that for ``HID_BPF_RDESC_FIXUP``, that memory is set to | |
32 | * ``4096`` (4 KB) | |
f5c27da4 BT |
33 | * @size: Valid data in the data field. |
34 | * | |
35 | * Programs can get the available valid size in data by fetching this field. | |
658ee5a6 BT |
36 | * Programs can also change this value by returning a positive number in the |
37 | * program. | |
38 | * To discard the event, return a negative error code. | |
39 | * | |
40 | * ``size`` must always be less or equal than ``allocated_size`` (it is enforced | |
41 | * once all BPF programs have been run). | |
42 | * @retval: Return value of the previous program. | |
c5958697 BT |
43 | * |
44 | * ``hid`` and ``allocated_size`` are read-only, ``size`` and ``retval`` are read-write. | |
f5c27da4 BT |
45 | */ |
46 | struct hid_bpf_ctx { | |
33c0fb85 | 47 | struct hid_device *hid; |
658ee5a6 | 48 | __u32 allocated_size; |
658ee5a6 BT |
49 | union { |
50 | __s32 retval; | |
51 | __s32 size; | |
52 | }; | |
f5c27da4 BT |
53 | }; |
54 | ||
f5c27da4 BT |
55 | /* |
56 | * Below is HID internal | |
57 | */ | |
58 | ||
f5c27da4 BT |
59 | #define HID_BPF_MAX_PROGS_PER_DEV 64 |
60 | #define HID_BPF_FLAG_MASK (((HID_BPF_FLAG_MAX - 1) << 1) - 1) | |
61 | ||
f5c27da4 | 62 | |
91a7f802 BT |
63 | struct hid_report_enum; |
64 | ||
146a06a0 | 65 | struct hid_ops { |
91a7f802 BT |
66 | struct hid_report *(*hid_get_report)(struct hid_report_enum *report_enum, const u8 *data); |
67 | int (*hid_hw_raw_request)(struct hid_device *hdev, | |
68 | unsigned char reportnum, __u8 *buf, | |
69 | size_t len, enum hid_report_type rtype, | |
67eccf15 | 70 | enum hid_class_request reqtype, |
762ced16 | 71 | u64 source, bool from_bpf); |
67eccf15 | 72 | int (*hid_hw_output_report)(struct hid_device *hdev, __u8 *buf, size_t len, |
762ced16 | 73 | u64 source, bool from_bpf); |
9be50ac3 | 74 | int (*hid_input_report)(struct hid_device *hid, enum hid_report_type type, |
9acbb7ba | 75 | u8 *data, u32 size, int interrupt, u64 source, bool from_bpf, |
fa03f398 | 76 | bool lock_already_taken); |
f5c27da4 | 77 | struct module *owner; |
9b0a3839 | 78 | const struct bus_type *bus_type; |
f5c27da4 BT |
79 | }; |
80 | ||
146a06a0 | 81 | extern struct hid_ops *hid_ops; |
f5c27da4 | 82 | |
ebc0d809 BT |
83 | /** |
84 | * struct hid_bpf_ops - A BPF struct_ops of callbacks allowing to attach HID-BPF | |
85 | * programs to a HID device | |
86 | * @hid_id: the HID uniq ID to attach to. This is writeable before ``load()``, and | |
87 | * cannot be changed after | |
88 | * @flags: flags used while attaching the struct_ops to the device. Currently only | |
89 | * available value is %0 or ``BPF_F_BEFORE``. | |
90 | * Writeable only before ``load()`` | |
91 | */ | |
92 | struct hid_bpf_ops { | |
93 | /* hid_id needs to stay first so we can easily change it | |
94 | * from userspace. | |
95 | */ | |
96 | int hid_id; | |
97 | u32 flags; | |
98 | ||
99 | /* private: do not show up in the docs */ | |
100 | struct list_head list; | |
101 | ||
102 | /* public: rest should show up in the docs */ | |
103 | ||
104 | /** | |
105 | * @hid_device_event: called whenever an event is coming in from the device | |
106 | * | |
107 | * It has the following arguments: | |
108 | * | |
109 | * ``ctx``: The HID-BPF context as &struct hid_bpf_ctx | |
110 | * | |
111 | * Return: %0 on success and keep processing; a positive | |
112 | * value to change the incoming size buffer; a negative | |
113 | * error code to interrupt the processing of this event | |
114 | * | |
115 | * Context: Interrupt context. | |
116 | */ | |
67eccf15 | 117 | int (*hid_device_event)(struct hid_bpf_ctx *ctx, enum hid_report_type report_type, |
762ced16 | 118 | u64 source); |
ebc0d809 BT |
119 | |
120 | /** | |
121 | * @hid_rdesc_fixup: called when the probe function parses the report descriptor | |
122 | * of the HID device | |
123 | * | |
124 | * It has the following arguments: | |
125 | * | |
126 | * ``ctx``: The HID-BPF context as &struct hid_bpf_ctx | |
127 | * | |
128 | * Return: %0 on success and keep processing; a positive | |
129 | * value to change the incoming size buffer; a negative | |
130 | * error code to interrupt the processing of this device | |
131 | */ | |
132 | int (*hid_rdesc_fixup)(struct hid_bpf_ctx *ctx); | |
133 | ||
8bd0488b BT |
134 | /** |
135 | * @hid_hw_request: called whenever a hid_hw_raw_request() call is emitted | |
136 | * on the HID device | |
137 | * | |
138 | * It has the following arguments: | |
139 | * | |
140 | * ``ctx``: The HID-BPF context as &struct hid_bpf_ctx | |
c79de517 | 141 | * |
8bd0488b | 142 | * ``reportnum``: the report number, as in hid_hw_raw_request() |
260ffc96 | 143 | * |
8bd0488b | 144 | * ``rtype``: the report type (``HID_INPUT_REPORT``, ``HID_FEATURE_REPORT``, |
260ffc96 BT |
145 | * ``HID_OUTPUT_REPORT``) |
146 | * | |
8bd0488b | 147 | * ``reqtype``: the request |
260ffc96 | 148 | * |
8bd0488b | 149 | * ``source``: a u64 referring to a uniq but identifiable source. If %0, the |
260ffc96 BT |
150 | * kernel itself emitted that call. For hidraw, ``source`` is set |
151 | * to the associated ``struct file *``. | |
8bd0488b BT |
152 | * |
153 | * Return: %0 to keep processing the request by hid-core; any other value | |
154 | * stops hid-core from processing that event. A positive value should be | |
155 | * returned with the number of bytes returned in the incoming buffer; a | |
156 | * negative error code interrupts the processing of this call. | |
157 | */ | |
158 | int (*hid_hw_request)(struct hid_bpf_ctx *ctx, unsigned char reportnum, | |
159 | enum hid_report_type rtype, enum hid_class_request reqtype, | |
260ffc96 | 160 | u64 source); |
8bd0488b | 161 | |
9286675a BT |
162 | /** |
163 | * @hid_hw_output_report: called whenever a hid_hw_output_report() call is emitted | |
164 | * on the HID device | |
165 | * | |
166 | * It has the following arguments: | |
167 | * | |
168 | * ``ctx``: The HID-BPF context as &struct hid_bpf_ctx | |
c79de517 | 169 | * |
9286675a | 170 | * ``source``: a u64 referring to a uniq but identifiable source. If %0, the |
c79de517 BT |
171 | * kernel itself emitted that call. For hidraw, ``source`` is set |
172 | * to the associated ``struct file *``. | |
9286675a BT |
173 | * |
174 | * Return: %0 to keep processing the request by hid-core; any other value | |
175 | * stops hid-core from processing that event. A positive value should be | |
176 | * returned with the number of bytes written to the device; a negative error | |
177 | * code interrupts the processing of this call. | |
178 | */ | |
c79de517 | 179 | int (*hid_hw_output_report)(struct hid_bpf_ctx *ctx, u64 source); |
9286675a | 180 | |
8bd0488b | 181 | |
ebc0d809 BT |
182 | /* private: do not show up in the docs */ |
183 | struct hid_device *hdev; | |
184 | }; | |
185 | ||
f5c27da4 BT |
186 | /* stored in each device */ |
187 | struct hid_bpf { | |
658ee5a6 BT |
188 | u8 *device_data; /* allocated when a bpf program of type |
189 | * SEC(f.../hid_bpf_device_event) has been attached | |
190 | * to this HID device | |
191 | */ | |
192 | u32 allocated_data; | |
f5c27da4 BT |
193 | bool destroyed; /* prevents the assignment of any progs */ |
194 | ||
ebc0d809 BT |
195 | struct hid_bpf_ops *rdesc_ops; |
196 | struct list_head prog_list; | |
197 | struct mutex prog_list_lock; /* protects prog_list update */ | |
6cd735f0 | 198 | struct srcu_struct srcu; /* protects prog_list read-only access */ |
f5c27da4 BT |
199 | }; |
200 | ||
201 | #ifdef CONFIG_HID_BPF | |
658ee5a6 | 202 | u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, u8 *data, |
9acbb7ba | 203 | u32 *size, int interrupt, u64 source, bool from_bpf); |
8bd0488b BT |
204 | int dispatch_hid_bpf_raw_requests(struct hid_device *hdev, |
205 | unsigned char reportnum, __u8 *buf, | |
206 | u32 size, enum hid_report_type rtype, | |
207 | enum hid_class_request reqtype, | |
c79de517 | 208 | u64 source, bool from_bpf); |
9286675a | 209 | int dispatch_hid_bpf_output_report(struct hid_device *hdev, __u8 *buf, u32 size, |
c79de517 | 210 | u64 source, bool from_bpf); |
658ee5a6 BT |
211 | int hid_bpf_connect_device(struct hid_device *hdev); |
212 | void hid_bpf_disconnect_device(struct hid_device *hdev); | |
f5c27da4 | 213 | void hid_bpf_destroy_device(struct hid_device *hid); |
6cd735f0 | 214 | int hid_bpf_device_init(struct hid_device *hid); |
ad190df1 | 215 | u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size); |
f5c27da4 | 216 | #else /* CONFIG_HID_BPF */ |
658ee5a6 | 217 | static inline u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, |
67eccf15 | 218 | u8 *data, u32 *size, int interrupt, |
9acbb7ba | 219 | u64 source, bool from_bpf) { return data; } |
8bd0488b BT |
220 | static inline int dispatch_hid_bpf_raw_requests(struct hid_device *hdev, |
221 | unsigned char reportnum, u8 *buf, | |
222 | u32 size, enum hid_report_type rtype, | |
223 | enum hid_class_request reqtype, | |
75839101 | 224 | u64 source, bool from_bpf) { return 0; } |
9286675a | 225 | static inline int dispatch_hid_bpf_output_report(struct hid_device *hdev, __u8 *buf, u32 size, |
c79de517 | 226 | u64 source, bool from_bpf) { return 0; } |
658ee5a6 BT |
227 | static inline int hid_bpf_connect_device(struct hid_device *hdev) { return 0; } |
228 | static inline void hid_bpf_disconnect_device(struct hid_device *hdev) {} | |
f5c27da4 | 229 | static inline void hid_bpf_destroy_device(struct hid_device *hid) {} |
6cd735f0 | 230 | static inline int hid_bpf_device_init(struct hid_device *hid) { return 0; } |
3b0ba54d SB |
231 | /* |
232 | * This specialized allocator has to be a macro for its allocations to be | |
233 | * accounted separately (to have a separate alloc_tag). The typecast is | |
234 | * intentional to enforce typesafety. | |
235 | */ | |
2c321f3f SB |
236 | #define call_hid_bpf_rdesc_fixup(_hdev, _rdesc, _size) \ |
237 | ((u8 *)kmemdup(_rdesc, *(_size), GFP_KERNEL)) | |
ad190df1 | 238 | |
f5c27da4 BT |
239 | #endif /* CONFIG_HID_BPF */ |
240 | ||
241 | #endif /* __HID_BPF_H */ |