Merge tag 'v6.3-p2' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-block.git] / Documentation / hid / hid-bpf.rst
1 .. SPDX-License-Identifier: GPL-2.0
2
3 =======
4 HID-BPF
5 =======
6
7 HID is a standard protocol for input devices but some devices may require
8 custom tweaks, traditionally done with a kernel driver fix. Using the eBPF
9 capabilities instead speeds up development and adds new capabilities to the
10 existing HID interfaces.
11
12 .. contents::
13     :local:
14     :depth: 2
15
16
17 When (and why) to use HID-BPF
18 =============================
19
20 There are several use cases when using HID-BPF is better
21 than standard kernel driver fix:
22
23 Dead zone of a joystick
24 -----------------------
25
26 Assuming you have a joystick that is getting older, it is common to see it
27 wobbling around its neutral point. This is usually filtered at the application
28 level by adding a *dead zone* for this specific axis.
29
30 With HID-BPF, we can apply this filtering in the kernel directly so userspace
31 does not get woken up when nothing else is happening on the input controller.
32
33 Of course, given that this dead zone is specific to an individual device, we
34 can not create a generic fix for all of the same joysticks. Adding a custom
35 kernel API for this (e.g. by adding a sysfs entry) does not guarantee this new
36 kernel API will be broadly adopted and maintained.
37
38 HID-BPF allows the userspace program to load the program itself, ensuring we
39 only load the custom API when we have a user.
40
41 Simple fixup of report descriptor
42 ---------------------------------
43
44 In the HID tree, half of the drivers only fix one key or one byte
45 in the report descriptor. These fixes all require a kernel patch and the
46 subsequent shepherding into a release, a long and painful process for users.
47
48 We can reduce this burden by providing an eBPF program instead. Once such a
49 program  has been verified by the user, we can embed the source code into the
50 kernel tree and ship the eBPF program and load it directly instead of loading
51 a specific kernel module for it.
52
53 Note: distribution of eBPF programs and their inclusion in the kernel is not
54 yet fully implemented
55
56 Add a new feature that requires a new kernel API
57 ------------------------------------------------
58
59 An example for such a feature are the Universal Stylus Interface (USI) pens.
60 Basically, USI pens require a new kernel API because there are new
61 channels of communication that our HID and input stack do not support.
62 Instead of using hidraw or creating new sysfs entries or ioctls, we can rely
63 on eBPF to have the kernel API controlled by the consumer and to not
64 impact the performances by waking up userspace every time there is an
65 event.
66
67 Morph a device into something else and control that from userspace
68 ------------------------------------------------------------------
69
70 The kernel has a relatively static mapping of HID items to evdev bits.
71 It cannot decide to dynamically transform a given device into something else
72 as it does not have the required context and any such transformation cannot be
73 undone (or even discovered) by userspace.
74
75 However, some devices are useless with that static way of defining devices. For
76 example, the Microsoft Surface Dial is a pushbutton with haptic feedback that
77 is barely usable as of today.
78
79 With eBPF, userspace can morph that device into a mouse, and convert the dial
80 events into wheel events. Also, the userspace program can set/unset the haptic
81 feedback depending on the context. For example, if a menu is visible on the
82 screen we likely need to have a haptic click every 15 degrees. But when
83 scrolling in a web page the user experience is better when the device emits
84 events at the highest resolution.
85
86 Firewall
87 --------
88
89 What if we want to prevent other users to access a specific feature of a
90 device? (think a possibly broken firmware update entry point)
91
92 With eBPF, we can intercept any HID command emitted to the device and
93 validate it or not.
94
95 This also allows to sync the state between the userspace and the
96 kernel/bpf program because we can intercept any incoming command.
97
98 Tracing
99 -------
100
101 The last usage is tracing events and all the fun we can do we BPF to summarize
102 and analyze events.
103
104 Right now, tracing relies on hidraw. It works well except for a couple
105 of issues:
106
107 1. if the driver doesn't export a hidraw node, we can't trace anything
108    (eBPF will be a "god-mode" there, so this may raise some eyebrows)
109 2. hidraw doesn't catch other processes' requests to the device, which
110    means that we have cases where we need to add printks to the kernel
111    to understand what is happening.
112
113 High-level view of HID-BPF
114 ==========================
115
116 The main idea behind HID-BPF is that it works at an array of bytes level.
117 Thus, all of the parsing of the HID report and the HID report descriptor
118 must be implemented in the userspace component that loads the eBPF
119 program.
120
121 For example, in the dead zone joystick from above, knowing which fields
122 in the data stream needs to be set to ``0`` needs to be computed by userspace.
123
124 A corollary of this is that HID-BPF doesn't know about the other subsystems
125 available in the kernel. *You can not directly emit input event through the
126 input API from eBPF*.
127
128 When a BPF program needs to emit input events, it needs to talk with the HID
129 protocol, and rely on the HID kernel processing to translate the HID data into
130 input events.
131
132 Available types of programs
133 ===========================
134
135 HID-BPF is built "on top" of BPF, meaning that we use tracing method to
136 declare our programs.
137
138 HID-BPF has the following attachment types available:
139
140 1. event processing/filtering with ``SEC("fmod_ret/hid_bpf_device_event")`` in libbpf
141 2. actions coming from userspace with ``SEC("syscall")`` in libbpf
142 3. change of the report descriptor with ``SEC("fmod_ret/hid_bpf_rdesc_fixup")`` in libbpf
143
144 A ``hid_bpf_device_event`` is calling a BPF program when an event is received from
145 the device. Thus we are in IRQ context and can act on the data or notify userspace.
146 And given that we are in IRQ context, we can not talk back to the device.
147
148 A ``syscall`` means that userspace called the syscall ``BPF_PROG_RUN`` facility.
149 This time, we can do any operations allowed by HID-BPF, and talking to the device is
150 allowed.
151
152 Last, ``hid_bpf_rdesc_fixup`` is different from the others as there can be only one
153 BPF program of this type. This is called on ``probe`` from the driver and allows to
154 change the report descriptor from the BPF program. Once a ``hid_bpf_rdesc_fixup``
155 program has been loaded, it is not possible to overwrite it unless the program which
156 inserted it allows us by pinning the program and closing all of its fds pointing to it.
157
158 Developer API:
159 ==============
160
161 User API data structures available in programs:
162 -----------------------------------------------
163
164 .. kernel-doc:: include/linux/hid_bpf.h
165
166 Available tracing functions to attach a HID-BPF program:
167 --------------------------------------------------------
168
169 .. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c
170    :functions: hid_bpf_device_event hid_bpf_rdesc_fixup
171
172 Available API that can be used in all HID-BPF programs:
173 -------------------------------------------------------
174
175 .. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c
176    :functions: hid_bpf_get_data
177
178 Available API that can be used in syscall HID-BPF programs:
179 -----------------------------------------------------------
180
181 .. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c
182    :functions: hid_bpf_attach_prog hid_bpf_hw_request hid_bpf_allocate_context hid_bpf_release_context
183
184 General overview of a HID-BPF program
185 =====================================
186
187 Accessing the data attached to the context
188 ------------------------------------------
189
190 The ``struct hid_bpf_ctx`` doesn't export the ``data`` fields directly and to access
191 it, a bpf program needs to first call :c:func:`hid_bpf_get_data`.
192
193 ``offset`` can be any integer, but ``size`` needs to be constant, known at compile
194 time.
195
196 This allows the following:
197
198 1. for a given device, if we know that the report length will always be of a certain value,
199    we can request the ``data`` pointer to point at the full report length.
200
201    The kernel will ensure we are using a correct size and offset and eBPF will ensure
202    the code will not attempt to read or write outside of the boundaries::
203
204      __u8 *data = hid_bpf_get_data(ctx, 0 /* offset */, 256 /* size */);
205
206      if (!data)
207          return 0; /* ensure data is correct, now the verifier knows we
208                     * have 256 bytes available */
209
210      bpf_printk("hello world: %02x %02x %02x", data[0], data[128], data[255]);
211
212 2. if the report length is variable, but we know the value of ``X`` is always a 16-bit
213    integer, we can then have a pointer to that value only::
214
215       __u16 *x = hid_bpf_get_data(ctx, offset, sizeof(*x));
216
217       if (!x)
218           return 0; /* something went wrong */
219
220       *x += 1; /* increment X by one */
221
222 Effect of a HID-BPF program
223 ---------------------------
224
225 For all HID-BPF attachment types except for :c:func:`hid_bpf_rdesc_fixup`, several eBPF
226 programs can be attached to the same device.
227
228 Unless ``HID_BPF_FLAG_INSERT_HEAD`` is added to the flags while attaching the
229 program, the new program is appended at the end of the list.
230 ``HID_BPF_FLAG_INSERT_HEAD`` will insert the new program at the beginning of the
231 list which is useful for e.g. tracing where we need to get the unprocessed events
232 from the device.
233
234 Note that if there are multiple programs using the ``HID_BPF_FLAG_INSERT_HEAD`` flag,
235 only the most recently loaded one is actually the first in the list.
236
237 ``SEC("fmod_ret/hid_bpf_device_event")``
238 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
239
240 Whenever a matching event is raised, the eBPF programs are called one after the other
241 and are working on the same data buffer.
242
243 If a program changes the data associated with the context, the next one will see
244 the modified data but it will have *no* idea of what the original data was.
245
246 Once all the programs are run and return ``0`` or a positive value, the rest of the
247 HID stack will work on the modified data, with the ``size`` field of the last hid_bpf_ctx
248 being the new size of the input stream of data.
249
250 A BPF program returning a negative error discards the event, i.e. this event will not be
251 processed by the HID stack. Clients (hidraw, input, LEDs) will **not** see this event.
252
253 ``SEC("syscall")``
254 ~~~~~~~~~~~~~~~~~~
255
256 ``syscall`` are not attached to a given device. To tell which device we are working
257 with, userspace needs to refer to the device by its unique system id (the last 4 numbers
258 in the sysfs path: ``/sys/bus/hid/devices/xxxx:yyyy:zzzz:0000``).
259
260 To retrieve a context associated with the device, the program must call
261 :c:func:`hid_bpf_allocate_context` and must release it with :c:func:`hid_bpf_release_context`
262 before returning.
263 Once the context is retrieved, one can also request a pointer to kernel memory with
264 :c:func:`hid_bpf_get_data`. This memory is big enough to support all input/output/feature
265 reports of the given device.
266
267 ``SEC("fmod_ret/hid_bpf_rdesc_fixup")``
268 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
269
270 The ``hid_bpf_rdesc_fixup`` program works in a similar manner to
271 ``.report_fixup`` of ``struct hid_driver``.
272
273 When the device is probed, the kernel sets the data buffer of the context with the
274 content of the report descriptor. The memory associated with that buffer is
275 ``HID_MAX_DESCRIPTOR_SIZE`` (currently 4kB).
276
277 The eBPF program can modify the data buffer at-will and the kernel uses the
278 modified content and size as the report descriptor.
279
280 Whenever a ``SEC("fmod_ret/hid_bpf_rdesc_fixup")`` program is attached (if no
281 program was attached before), the kernel immediately disconnects the HID device
282 and does a reprobe.
283
284 In the same way, when the ``SEC("fmod_ret/hid_bpf_rdesc_fixup")`` program is
285 detached, the kernel issues a disconnect on the device.
286
287 There is no ``detach`` facility in HID-BPF. Detaching a program happens when
288 all the user space file descriptors pointing at a program are closed.
289 Thus, if we need to replace a report descriptor fixup, some cooperation is
290 required from the owner of the original report descriptor fixup.
291 The previous owner will likely pin the program in the bpffs, and we can then
292 replace it through normal bpf operations.
293
294 Attaching a bpf program to a device
295 ===================================
296
297 ``libbpf`` does not export any helper to attach a HID-BPF program.
298 Users need to use a dedicated ``syscall`` program which will call
299 ``hid_bpf_attach_prog(hid_id, program_fd, flags)``.
300
301 ``hid_id`` is the unique system ID of the HID device (the last 4 numbers in the
302 sysfs path: ``/sys/bus/hid/devices/xxxx:yyyy:zzzz:0000``)
303
304 ``progam_fd`` is the opened file descriptor of the program to attach.
305
306 ``flags`` is of type ``enum hid_bpf_attach_flags``.
307
308 We can not rely on hidraw to bind a BPF program to a HID device. hidraw is an
309 artefact of the processing of the HID device, and is not stable. Some drivers
310 even disable it, so that removes the tracing capabilities on those devices
311 (where it is interesting to get the non-hidraw traces).
312
313 On the other hand, the ``hid_id`` is stable for the entire life of the HID device,
314 even if we change its report descriptor.
315
316 Given that hidraw is not stable when the device disconnects/reconnects, we recommend
317 accessing the current report descriptor of the device through the sysfs.
318 This is available at ``/sys/bus/hid/devices/BUS:VID:PID.000N/report_descriptor`` as a
319 binary stream.
320
321 Parsing the report descriptor is the responsibility of the BPF programmer or the userspace
322 component that loads the eBPF program.
323
324 An (almost) complete example of a BPF enhanced HID device
325 =========================================================
326
327 *Foreword: for most parts, this could be implemented as a kernel driver*
328
329 Let's imagine we have a new tablet device that has some haptic capabilities
330 to simulate the surface the user is scratching on. This device would also have
331 a specific 3 positions switch to toggle between *pencil on paper*, *cray on a wall*
332 and *brush on a painting canvas*. To make things even better, we can control the
333 physical position of the switch through a feature report.
334
335 And of course, the switch is relying on some userspace component to control the
336 haptic feature of the device itself.
337
338 Filtering events
339 ----------------
340
341 The first step consists in filtering events from the device. Given that the switch
342 position is actually reported in the flow of the pen events, using hidraw to implement
343 that filtering would mean that we wake up userspace for every single event.
344
345 This is OK for libinput, but having an external library that is just interested in
346 one byte in the report is less than ideal.
347
348 For that, we can create a basic skeleton for our BPF program::
349
350   #include "vmlinux.h"
351   #include <bpf/bpf_helpers.h>
352   #include <bpf/bpf_tracing.h>
353
354   /* HID programs need to be GPL */
355   char _license[] SEC("license") = "GPL";
356
357   /* HID-BPF kfunc API definitions */
358   extern __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx,
359                               unsigned int offset,
360                               const size_t __sz) __ksym;
361   extern int hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, u32 flags) __ksym;
362
363   struct {
364         __uint(type, BPF_MAP_TYPE_RINGBUF);
365         __uint(max_entries, 4096 * 64);
366   } ringbuf SEC(".maps");
367
368   struct attach_prog_args {
369         int prog_fd;
370         unsigned int hid;
371         unsigned int flags;
372         int retval;
373   };
374
375   SEC("syscall")
376   int attach_prog(struct attach_prog_args *ctx)
377   {
378         ctx->retval = hid_bpf_attach_prog(ctx->hid,
379                                           ctx->prog_fd,
380                                           ctx->flags);
381         return 0;
382   }
383
384   __u8 current_value = 0;
385
386   SEC("?fmod_ret/hid_bpf_device_event")
387   int BPF_PROG(filter_switch, struct hid_bpf_ctx *hid_ctx)
388   {
389         __u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 192 /* size */);
390         __u8 *buf;
391
392         if (!data)
393                 return 0; /* EPERM check */
394
395         if (current_value != data[152]) {
396                 buf = bpf_ringbuf_reserve(&ringbuf, 1, 0);
397                 if (!buf)
398                         return 0;
399
400                 *buf = data[152];
401
402                 bpf_ringbuf_commit(buf, 0);
403
404                 current_value = data[152];
405         }
406
407         return 0;
408   }
409
410 To attach ``filter_switch``, userspace needs to call the ``attach_prog`` syscall
411 program first::
412
413   static int attach_filter(struct hid *hid_skel, int hid_id)
414   {
415         int err, prog_fd;
416         int ret = -1;
417         struct attach_prog_args args = {
418                 .hid = hid_id,
419         };
420         DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattrs,
421                 .ctx_in = &args,
422                 .ctx_size_in = sizeof(args),
423         );
424
425         args.prog_fd = bpf_program__fd(hid_skel->progs.filter_switch);
426
427         prog_fd = bpf_program__fd(hid_skel->progs.attach_prog);
428
429         err = bpf_prog_test_run_opts(prog_fd, &tattrs);
430         if (err)
431                 return err;
432
433         return args.retval; /* the fd of the created bpf_link */
434   }
435
436 Our userspace program can now listen to notifications on the ring buffer, and
437 is awaken only when the value changes.
438
439 When the userspace program doesn't need to listen to events anymore, it can just
440 close the returned fd from :c:func:`attach_filter`, which will tell the kernel to
441 detach the program from the HID device.
442
443 Of course, in other use cases, the userspace program can also pin the fd to the
444 BPF filesystem through a call to :c:func:`bpf_obj_pin`, as with any bpf_link.
445
446 Controlling the device
447 ----------------------
448
449 To be able to change the haptic feedback from the tablet, the userspace program
450 needs to emit a feature report on the device itself.
451
452 Instead of using hidraw for that, we can create a ``SEC("syscall")`` program
453 that talks to the device::
454
455   /* some more HID-BPF kfunc API definitions */
456   extern struct hid_bpf_ctx *hid_bpf_allocate_context(unsigned int hid_id) __ksym;
457   extern void hid_bpf_release_context(struct hid_bpf_ctx *ctx) __ksym;
458   extern int hid_bpf_hw_request(struct hid_bpf_ctx *ctx,
459                               __u8* data,
460                               size_t len,
461                               enum hid_report_type type,
462                               enum hid_class_request reqtype) __ksym;
463
464
465   struct hid_send_haptics_args {
466         /* data needs to come at offset 0 so we can do a memcpy into it */
467         __u8 data[10];
468         unsigned int hid;
469   };
470
471   SEC("syscall")
472   int send_haptic(struct hid_send_haptics_args *args)
473   {
474         struct hid_bpf_ctx *ctx;
475         int ret = 0;
476
477         ctx = hid_bpf_allocate_context(args->hid);
478         if (!ctx)
479                 return 0; /* EPERM check */
480
481         ret = hid_bpf_hw_request(ctx,
482                                  args->data,
483                                  10,
484                                  HID_FEATURE_REPORT,
485                                  HID_REQ_SET_REPORT);
486
487         hid_bpf_release_context(ctx);
488
489         return ret;
490   }
491
492 And then userspace needs to call that program directly::
493
494   static int set_haptic(struct hid *hid_skel, int hid_id, __u8 haptic_value)
495   {
496         int err, prog_fd;
497         int ret = -1;
498         struct hid_send_haptics_args args = {
499                 .hid = hid_id,
500         };
501         DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattrs,
502                 .ctx_in = &args,
503                 .ctx_size_in = sizeof(args),
504         );
505
506         args.data[0] = 0x02; /* report ID of the feature on our device */
507         args.data[1] = haptic_value;
508
509         prog_fd = bpf_program__fd(hid_skel->progs.set_haptic);
510
511         err = bpf_prog_test_run_opts(prog_fd, &tattrs);
512         return err;
513   }
514
515 Now our userspace program is aware of the haptic state and can control it. The
516 program could make this state further available to other userspace programs
517 (e.g. via a DBus API).
518
519 The interesting bit here is that we did not created a new kernel API for this.
520 Which means that if there is a bug in our implementation, we can change the
521 interface with the kernel at-will, because the userspace application is
522 responsible for its own usage.