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 BT |
79 | |
80 | /* Following functions are kfunc that we export to BPF programs */ | |
91a7f802 | 81 | /* available everywhere in HID-BPF */ |
f5c27da4 BT |
82 | __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t __sz); |
83 | ||
84 | /* only available in syscall */ | |
85 | int hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags); | |
91a7f802 BT |
86 | int hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz, |
87 | enum hid_report_type rtype, enum hid_class_request reqtype); | |
88 | struct hid_bpf_ctx *hid_bpf_allocate_context(unsigned int hid_id); | |
89 | void hid_bpf_release_context(struct hid_bpf_ctx *ctx); | |
f5c27da4 BT |
90 | |
91 | /* | |
92 | * Below is HID internal | |
93 | */ | |
94 | ||
95 | /* internal function to call eBPF programs, not to be used by anybody */ | |
96 | int __hid_bpf_tail_call(struct hid_bpf_ctx *ctx); | |
97 | ||
98 | #define HID_BPF_MAX_PROGS_PER_DEV 64 | |
99 | #define HID_BPF_FLAG_MASK (((HID_BPF_FLAG_MAX - 1) << 1) - 1) | |
100 | ||
101 | /* types of HID programs to attach to */ | |
102 | enum hid_bpf_prog_type { | |
103 | HID_BPF_PROG_TYPE_UNDEF = -1, | |
104 | HID_BPF_PROG_TYPE_DEVICE_EVENT, /* an event is emitted from the device */ | |
ad190df1 | 105 | HID_BPF_PROG_TYPE_RDESC_FIXUP, |
f5c27da4 BT |
106 | HID_BPF_PROG_TYPE_MAX, |
107 | }; | |
108 | ||
91a7f802 BT |
109 | struct hid_report_enum; |
110 | ||
f5c27da4 | 111 | struct hid_bpf_ops { |
91a7f802 BT |
112 | struct hid_report *(*hid_get_report)(struct hid_report_enum *report_enum, const u8 *data); |
113 | int (*hid_hw_raw_request)(struct hid_device *hdev, | |
114 | unsigned char reportnum, __u8 *buf, | |
115 | size_t len, enum hid_report_type rtype, | |
116 | enum hid_class_request reqtype); | |
f5c27da4 BT |
117 | struct module *owner; |
118 | struct bus_type *bus_type; | |
119 | }; | |
120 | ||
121 | extern struct hid_bpf_ops *hid_bpf_ops; | |
122 | ||
123 | struct hid_bpf_prog_list { | |
124 | u16 prog_idx[HID_BPF_MAX_PROGS_PER_DEV]; | |
125 | u8 prog_cnt; | |
126 | }; | |
127 | ||
128 | /* stored in each device */ | |
129 | struct hid_bpf { | |
658ee5a6 BT |
130 | u8 *device_data; /* allocated when a bpf program of type |
131 | * SEC(f.../hid_bpf_device_event) has been attached | |
132 | * to this HID device | |
133 | */ | |
134 | u32 allocated_data; | |
135 | ||
f5c27da4 BT |
136 | struct hid_bpf_prog_list __rcu *progs[HID_BPF_PROG_TYPE_MAX]; /* attached BPF progs */ |
137 | bool destroyed; /* prevents the assignment of any progs */ | |
138 | ||
139 | spinlock_t progs_lock; /* protects RCU update of progs */ | |
140 | }; | |
141 | ||
4b9a3f49 BT |
142 | /* specific HID-BPF link when a program is attached to a device */ |
143 | struct hid_bpf_link { | |
144 | struct bpf_link link; | |
145 | int hid_table_index; | |
146 | }; | |
147 | ||
f5c27da4 | 148 | #ifdef CONFIG_HID_BPF |
658ee5a6 BT |
149 | u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, u8 *data, |
150 | u32 *size, int interrupt); | |
151 | int hid_bpf_connect_device(struct hid_device *hdev); | |
152 | void hid_bpf_disconnect_device(struct hid_device *hdev); | |
f5c27da4 BT |
153 | void hid_bpf_destroy_device(struct hid_device *hid); |
154 | void hid_bpf_device_init(struct hid_device *hid); | |
ad190df1 | 155 | u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size); |
f5c27da4 | 156 | #else /* CONFIG_HID_BPF */ |
658ee5a6 | 157 | static inline u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, |
576e619b | 158 | u8 *data, u32 *size, int interrupt) { return data; } |
658ee5a6 BT |
159 | static inline int hid_bpf_connect_device(struct hid_device *hdev) { return 0; } |
160 | static inline void hid_bpf_disconnect_device(struct hid_device *hdev) {} | |
f5c27da4 BT |
161 | static inline void hid_bpf_destroy_device(struct hid_device *hid) {} |
162 | static inline void hid_bpf_device_init(struct hid_device *hid) {} | |
ad190df1 BT |
163 | static inline u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size) |
164 | { | |
165 | return kmemdup(rdesc, *size, GFP_KERNEL); | |
166 | } | |
167 | ||
f5c27da4 BT |
168 | #endif /* CONFIG_HID_BPF */ |
169 | ||
170 | #endif /* __HID_BPF_H */ |