| 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
| 2 | |
| 3 | #ifndef __HID_BPF_H |
| 4 | #define __HID_BPF_H |
| 5 | |
| 6 | #include <linux/bpf.h> |
| 7 | #include <linux/mutex.h> |
| 8 | #include <linux/srcu.h> |
| 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 |
| 24 | * a call to hid_bpf_get_data() in order to get a pointer to that field. |
| 25 | * |
| 26 | * @hid: the &struct hid_device representing the device itself |
| 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) |
| 33 | * @size: Valid data in the data field. |
| 34 | * |
| 35 | * Programs can get the available valid size in data by fetching this field. |
| 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. |
| 43 | * |
| 44 | * ``hid`` and ``allocated_size`` are read-only, ``size`` and ``retval`` are read-write. |
| 45 | */ |
| 46 | struct hid_bpf_ctx { |
| 47 | struct hid_device *hid; |
| 48 | __u32 allocated_size; |
| 49 | union { |
| 50 | __s32 retval; |
| 51 | __s32 size; |
| 52 | }; |
| 53 | }; |
| 54 | |
| 55 | /* |
| 56 | * Below is HID internal |
| 57 | */ |
| 58 | |
| 59 | #define HID_BPF_MAX_PROGS_PER_DEV 64 |
| 60 | #define HID_BPF_FLAG_MASK (((HID_BPF_FLAG_MAX - 1) << 1) - 1) |
| 61 | |
| 62 | |
| 63 | struct hid_report_enum; |
| 64 | |
| 65 | struct hid_ops { |
| 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, |
| 70 | enum hid_class_request reqtype, |
| 71 | u64 source, bool from_bpf); |
| 72 | int (*hid_hw_output_report)(struct hid_device *hdev, __u8 *buf, size_t len, |
| 73 | u64 source, bool from_bpf); |
| 74 | int (*hid_input_report)(struct hid_device *hid, enum hid_report_type type, |
| 75 | u8 *data, u32 size, int interrupt, u64 source, bool from_bpf, |
| 76 | bool lock_already_taken); |
| 77 | struct module *owner; |
| 78 | const struct bus_type *bus_type; |
| 79 | }; |
| 80 | |
| 81 | extern const struct hid_ops *hid_ops; |
| 82 | |
| 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 | */ |
| 117 | int (*hid_device_event)(struct hid_bpf_ctx *ctx, enum hid_report_type report_type, |
| 118 | u64 source); |
| 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 | |
| 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 |
| 141 | * |
| 142 | * ``reportnum``: the report number, as in hid_hw_raw_request() |
| 143 | * |
| 144 | * ``rtype``: the report type (``HID_INPUT_REPORT``, ``HID_FEATURE_REPORT``, |
| 145 | * ``HID_OUTPUT_REPORT``) |
| 146 | * |
| 147 | * ``reqtype``: the request |
| 148 | * |
| 149 | * ``source``: a u64 referring to a uniq but identifiable source. If %0, the |
| 150 | * kernel itself emitted that call. For hidraw, ``source`` is set |
| 151 | * to the associated ``struct file *``. |
| 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, |
| 160 | u64 source); |
| 161 | |
| 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 |
| 169 | * |
| 170 | * ``source``: a u64 referring to a uniq but identifiable source. If %0, the |
| 171 | * kernel itself emitted that call. For hidraw, ``source`` is set |
| 172 | * to the associated ``struct file *``. |
| 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 | */ |
| 179 | int (*hid_hw_output_report)(struct hid_bpf_ctx *ctx, u64 source); |
| 180 | |
| 181 | |
| 182 | /* private: do not show up in the docs */ |
| 183 | struct hid_device *hdev; |
| 184 | }; |
| 185 | |
| 186 | /* stored in each device */ |
| 187 | struct hid_bpf { |
| 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; |
| 193 | bool destroyed; /* prevents the assignment of any progs */ |
| 194 | |
| 195 | struct hid_bpf_ops *rdesc_ops; |
| 196 | struct list_head prog_list; |
| 197 | struct mutex prog_list_lock; /* protects prog_list update */ |
| 198 | struct srcu_struct srcu; /* protects prog_list read-only access */ |
| 199 | }; |
| 200 | |
| 201 | #ifdef CONFIG_HID_BPF |
| 202 | u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, u8 *data, |
| 203 | u32 *size, int interrupt, u64 source, bool from_bpf); |
| 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, |
| 208 | u64 source, bool from_bpf); |
| 209 | int dispatch_hid_bpf_output_report(struct hid_device *hdev, __u8 *buf, u32 size, |
| 210 | u64 source, bool from_bpf); |
| 211 | int hid_bpf_connect_device(struct hid_device *hdev); |
| 212 | void hid_bpf_disconnect_device(struct hid_device *hdev); |
| 213 | void hid_bpf_destroy_device(struct hid_device *hid); |
| 214 | int hid_bpf_device_init(struct hid_device *hid); |
| 215 | const u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size); |
| 216 | #else /* CONFIG_HID_BPF */ |
| 217 | static inline u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, |
| 218 | u8 *data, u32 *size, int interrupt, |
| 219 | u64 source, bool from_bpf) { return data; } |
| 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, |
| 224 | u64 source, bool from_bpf) { return 0; } |
| 225 | static inline int dispatch_hid_bpf_output_report(struct hid_device *hdev, __u8 *buf, u32 size, |
| 226 | u64 source, bool from_bpf) { return 0; } |
| 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) {} |
| 229 | static inline void hid_bpf_destroy_device(struct hid_device *hid) {} |
| 230 | static inline int hid_bpf_device_init(struct hid_device *hid) { return 0; } |
| 231 | static inline const u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, |
| 232 | unsigned int *size) { return rdesc; } |
| 233 | |
| 234 | #endif /* CONFIG_HID_BPF */ |
| 235 | |
| 236 | #endif /* __HID_BPF_H */ |
| 237 | |