Skip to content

Commit 6e504d2

Browse files
committed
Merge tag 'for-linus-2024071601' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID updates from Benjamin Tissoires: - rewrite of the HID-BPF internal implementation to use bpf struct_ops instead of a tracing endpoint (Benjamin Tissoires) - add two new HID-BPF hooks to be able to intercept userspace calls targeting a HID device and filtering them (Benjamin Tissoires) - add support for various new devices through HID-BPF filters (Benjamin Tissoires) - add support for the magic keyboard backlight (Orlando Chamberlain) - add the missing MODULE_DESCRIPTION() macros in HID drivers (Jeff Johnson) - use of kvzalloc in case memory gets too fragmented (Hailong Liu) - retrieve the device firmware node in the child HID device (Danny Kaehn) - some hid-uclogic improvements (José Expósito) - some more typos, trivial fixes, kernel doctext and unused functions cleanups * tag 'for-linus-2024071601' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (60 commits) HID: hid-steam: Fix typo in goto label HID: mcp2221: Remove unnecessary semicolon HID: Fix spelling mistakes "Kensigton" -> "Kensington" HID: add more missing MODULE_DESCRIPTION() macros HID: samples: fix the 2 struct_ops definitions HID: fix for amples in for-6.11/bpf HID: apple: Add support for magic keyboard backlight on T2 Macs HID: bpf: Thrustmaster TCA Yoke Boeing joystick fix HID: bpf: Add Huion Dial 2 bpf fixup HID: bpf: Add support for the XP-PEN Deco Mini 4 HID: bpf: move the BIT() macro to hid_bpf_helpers.h HID: bpf: add a driver for the Huion Inspiroy 2S (H641P) HID: bpf: Add a HID report composition helper macros HID: bpf: doc fixes for hid_hw_request() hooks HID: bpf: doc fixes for hid_hw_request() hooks HID: bpf: fix gcc warning and unify __u64 into u64 selftests/hid: ensure CKI can compile our new tests on old kernels selftests/hid: add an infinite loop test for hid_bpf_try_input_report selftests/hid: add another test for injecting an event from an event hook HID: bpf: allow hid_device_event hooks to inject input reports on self ...
2 parents 221fd1e + 30b8664 commit 6e504d2

File tree

114 files changed

+6443
-1579
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+6443
-1579
lines changed

Documentation/hid/hid-bpf.rst

Lines changed: 89 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -129,57 +129,80 @@ When a BPF program needs to emit input events, it needs to talk with the HID
129129
protocol, and rely on the HID kernel processing to translate the HID data into
130130
input events.
131131

132+
In-tree HID-BPF programs and ``udev-hid-bpf``
133+
=============================================
134+
135+
Official device fixes are shipped in the kernel tree as source in the
136+
``drivers/hid/bpf/progs`` directory. This allows to add selftests to them in
137+
``tools/testing/selftests/hid``.
138+
139+
However, the compilation of these objects is not part of a regular kernel compilation
140+
given that they need an external tool to be loaded. This tool is currently
141+
`udev-hid-bpf <https://libevdev.pages.freedesktop.org/udev-hid-bpf/index.html>`_.
142+
143+
For convenience, that external repository duplicates the files from here in
144+
``drivers/hid/bpf/progs`` into its own ``src/bpf/stable`` directory. This allows
145+
distributions to not have to pull the entire kernel source tree to ship and package
146+
those HID-BPF fixes. ``udev-hid-bpf`` also has capabilities of handling multiple
147+
objects files depending on the kernel the user is running.
148+
132149
Available types of programs
133150
===========================
134151

135-
HID-BPF is built "on top" of BPF, meaning that we use tracing method to
152+
HID-BPF is built "on top" of BPF, meaning that we use bpf struct_ops method to
136153
declare our programs.
137154

138155
HID-BPF has the following attachment types available:
139156

140-
1. event processing/filtering with ``SEC("fmod_ret/hid_bpf_device_event")`` in libbpf
157+
1. event processing/filtering with ``SEC("struct_ops/hid_device_event")`` in libbpf
141158
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
159+
3. change of the report descriptor with ``SEC("struct_ops/hid_rdesc_fixup")`` or
160+
``SEC("struct_ops.s/hid_rdesc_fixup")`` in libbpf
143161

144-
A ``hid_bpf_device_event`` is calling a BPF program when an event is received from
162+
A ``hid_device_event`` is calling a BPF program when an event is received from
145163
the device. Thus we are in IRQ context and can act on the data or notify userspace.
146164
And given that we are in IRQ context, we can not talk back to the device.
147165

148166
A ``syscall`` means that userspace called the syscall ``BPF_PROG_RUN`` facility.
149167
This time, we can do any operations allowed by HID-BPF, and talking to the device is
150168
allowed.
151169

152-
Last, ``hid_bpf_rdesc_fixup`` is different from the others as there can be only one
170+
Last, ``hid_rdesc_fixup`` is different from the others as there can be only one
153171
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``
172+
change the report descriptor from the BPF program. Once a ``hid_rdesc_fixup``
155173
program has been loaded, it is not possible to overwrite it unless the program which
156174
inserted it allows us by pinning the program and closing all of its fds pointing to it.
157175

176+
Note that ``hid_rdesc_fixup`` can be declared as sleepable (``SEC("struct_ops.s/hid_rdesc_fixup")``).
177+
178+
158179
Developer API:
159180
==============
160181

161-
User API data structures available in programs:
162-
-----------------------------------------------
182+
Available ``struct_ops`` for HID-BPF:
183+
-------------------------------------
163184

164185
.. kernel-doc:: include/linux/hid_bpf.h
186+
:identifiers: hid_bpf_ops
165187

166-
Available tracing functions to attach a HID-BPF program:
167-
--------------------------------------------------------
168188

169-
.. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c
170-
:functions: hid_bpf_device_event hid_bpf_rdesc_fixup
189+
User API data structures available in programs:
190+
-----------------------------------------------
171191

172-
Available API that can be used in all HID-BPF programs:
173-
-------------------------------------------------------
192+
.. kernel-doc:: include/linux/hid_bpf.h
193+
:identifiers: hid_bpf_ctx
194+
195+
Available API that can be used in all HID-BPF struct_ops programs:
196+
------------------------------------------------------------------
174197

175198
.. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c
176-
:functions: hid_bpf_get_data
199+
:identifiers: hid_bpf_get_data
177200

178-
Available API that can be used in syscall HID-BPF programs:
179-
-----------------------------------------------------------
201+
Available API that can be used in syscall HID-BPF programs or in sleepable HID-BPF struct_ops programs:
202+
-------------------------------------------------------------------------------------------------------
180203

181204
.. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c
182-
:functions: hid_bpf_attach_prog hid_bpf_hw_request hid_bpf_hw_output_report hid_bpf_input_report hid_bpf_allocate_context hid_bpf_release_context
205+
:identifiers: hid_bpf_hw_request hid_bpf_hw_output_report hid_bpf_input_report hid_bpf_try_input_report hid_bpf_allocate_context hid_bpf_release_context
183206

184207
General overview of a HID-BPF program
185208
=====================================
@@ -222,20 +245,21 @@ This allows the following:
222245
Effect of a HID-BPF program
223246
---------------------------
224247

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.
248+
For all HID-BPF attachment types except for :c:func:`hid_rdesc_fixup`, several eBPF
249+
programs can be attached to the same device. If a HID-BPF struct_ops has a
250+
:c:func:`hid_rdesc_fixup` while another is already attached to the device, the
251+
kernel will return `-EINVAL` when attaching the struct_ops.
227252

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.
253+
Unless ``BPF_F_BEFORE`` is added to the flags while attaching the program, the new
254+
program is appended at the end of the list.
255+
``BPF_F_BEFORE`` will insert the new program at the beginning of the list which is
256+
useful for e.g. tracing where we need to get the unprocessed events from the device.
233257

234-
Note that if there are multiple programs using the ``HID_BPF_FLAG_INSERT_HEAD`` flag,
258+
Note that if there are multiple programs using the ``BPF_F_BEFORE`` flag,
235259
only the most recently loaded one is actually the first in the list.
236260

237-
``SEC("fmod_ret/hid_bpf_device_event")``
238-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
261+
``SEC("struct_ops/hid_device_event")``
262+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
239263

240264
Whenever a matching event is raised, the eBPF programs are called one after the other
241265
and are working on the same data buffer.
@@ -258,17 +282,17 @@ with, userspace needs to refer to the device by its unique system id (the last 4
258282
in the sysfs path: ``/sys/bus/hid/devices/xxxx:yyyy:zzzz:0000``).
259283

260284
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`
285+
hid_bpf_allocate_context() and must release it with hid_bpf_release_context()
262286
before returning.
263287
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
288+
hid_bpf_get_data(). This memory is big enough to support all input/output/feature
265289
reports of the given device.
266290

267-
``SEC("fmod_ret/hid_bpf_rdesc_fixup")``
268-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
291+
``SEC("struct_ops/hid_rdesc_fixup")``
292+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
269293

270-
The ``hid_bpf_rdesc_fixup`` program works in a similar manner to
271-
``.report_fixup`` of ``struct hid_driver``.
294+
The ``hid_rdesc_fixup`` program works in a similar manner to ``.report_fixup``
295+
of ``struct hid_driver``.
272296

273297
When the device is probed, the kernel sets the data buffer of the context with the
274298
content of the report descriptor. The memory associated with that buffer is
@@ -277,33 +301,31 @@ content of the report descriptor. The memory associated with that buffer is
277301
The eBPF program can modify the data buffer at-will and the kernel uses the
278302
modified content and size as the report descriptor.
279303

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.
304+
Whenever a struct_ops containing a ``SEC("struct_ops/hid_rdesc_fixup")`` program
305+
is attached (if no program was attached before), the kernel immediately disconnects
306+
the HID device and does a reprobe.
283307

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.
308+
In the same way, when this struct_ops is detached, the kernel issues a disconnect
309+
on the device.
286310

287311
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.
312+
all the user space file descriptors pointing at a HID-BPF struct_ops link are closed.
289313
Thus, if we need to replace a report descriptor fixup, some cooperation is
290314
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
315+
The previous owner will likely pin the struct_ops link in the bpffs, and we can then
292316
replace it through normal bpf operations.
293317

294318
Attaching a bpf program to a device
295319
===================================
296320

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)``.
321+
We now use standard struct_ops attachment through ``bpf_map__attach_struct_ops()``.
322+
But given that we need to attach a struct_ops to a dedicated HID device, the caller
323+
must set ``hid_id`` in the struct_ops map before loading the program in the kernel.
300324

301325
``hid_id`` is the unique system ID of the HID device (the last 4 numbers in the
302326
sysfs path: ``/sys/bus/hid/devices/xxxx:yyyy:zzzz:0000``)
303327

304-
``progam_fd`` is the opened file descriptor of the program to attach.
305-
306-
``flags`` is of type ``enum hid_bpf_attach_flags``.
328+
One can also set ``flags``, which is of type ``enum hid_bpf_attach_flags``.
307329

308330
We can not rely on hidraw to bind a BPF program to a HID device. hidraw is an
309331
artefact of the processing of the HID device, and is not stable. Some drivers
@@ -358,32 +380,15 @@ For that, we can create a basic skeleton for our BPF program::
358380
extern __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx,
359381
unsigned int offset,
360382
const size_t __sz) __ksym;
361-
extern int hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, u32 flags) __ksym;
362383

363384
struct {
364385
__uint(type, BPF_MAP_TYPE_RINGBUF);
365386
__uint(max_entries, 4096 * 64);
366387
} ringbuf SEC(".maps");
367388

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-
384389
__u8 current_value = 0;
385390

386-
SEC("?fmod_ret/hid_bpf_device_event")
391+
SEC("struct_ops/hid_device_event")
387392
int BPF_PROG(filter_switch, struct hid_bpf_ctx *hid_ctx)
388393
{
389394
__u8 *data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 192 /* size */);
@@ -407,37 +412,37 @@ For that, we can create a basic skeleton for our BPF program::
407412
return 0;
408413
}
409414

410-
To attach ``filter_switch``, userspace needs to call the ``attach_prog`` syscall
411-
program first::
415+
SEC(".struct_ops.link")
416+
struct hid_bpf_ops haptic_tablet = {
417+
.hid_device_event = (void *)filter_switch,
418+
};
419+
420+
421+
To attach ``haptic_tablet``, userspace needs to set ``hid_id`` first::
412422

413423
static int attach_filter(struct hid *hid_skel, int hid_id)
414424
{
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-
);
425+
int err, link_fd;
424426

425-
args.prog_fd = bpf_program__fd(hid_skel->progs.filter_switch);
427+
hid_skel->struct_ops.haptic_tablet->hid_id = hid_id;
428+
err = hid__load(skel);
429+
if (err)
430+
return err;
426431

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+
link_fd = bpf_map__attach_struct_ops(hid_skel->maps.haptic_tablet);
433+
if (!link_fd) {
434+
fprintf(stderr, "can not attach HID-BPF program: %m\n");
435+
return -1;
436+
}
432437

433-
return args.retval; /* the fd of the created bpf_link */
438+
return link_fd; /* the fd of the created bpf_link */
434439
}
435440

436441
Our userspace program can now listen to notifications on the ring buffer, and
437442
is awaken only when the value changes.
438443

439444
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
445+
close the returned bpf link from :c:func:`attach_filter`, which will tell the kernel to
441446
detach the program from the HID device.
442447

443448
Of course, in other use cases, the userspace program can also pin the fd to the

drivers/hid/Makefile

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,8 @@ obj-$(CONFIG_HID_WINWING) += hid-winwing.o
154154
obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o
155155
obj-$(CONFIG_HID_SENSOR_CUSTOM_SENSOR) += hid-sensor-custom.o
156156

157-
hid-uclogic-test-objs := hid-uclogic-rdesc.o \
158-
hid-uclogic-params.o \
159-
hid-uclogic-rdesc-test.o
160-
obj-$(CONFIG_HID_KUNIT_TEST) += hid-uclogic-test.o
157+
hid-uclogic-test-objs := hid-uclogic-rdesc-test.o
158+
obj-$(CONFIG_HID_KUNIT_TEST) += hid-uclogic.o hid-uclogic-test.o
161159

162160
obj-$(CONFIG_USB_HID) += usbhid/
163161
obj-$(CONFIG_USB_MOUSE) += usbhid/

drivers/hid/bpf/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ LIBBPF_INCLUDE = $(srctree)/tools/lib
88
obj-$(CONFIG_HID_BPF) += hid_bpf.o
99
CFLAGS_hid_bpf_dispatch.o += -I$(LIBBPF_INCLUDE)
1010
CFLAGS_hid_bpf_jmp_table.o += -I$(LIBBPF_INCLUDE)
11-
hid_bpf-objs += hid_bpf_dispatch.o hid_bpf_jmp_table.o
11+
hid_bpf-objs += hid_bpf_dispatch.o hid_bpf_struct_ops.o

0 commit comments

Comments
 (0)