2024-06-07 15:34:52

by Benjamin Tissoires

[permalink] [raw]
Subject: [PATCH HID v2 00/16] HID: convert HID-BPF into using bpf_struct_ops

The purpose of this series is to rethink how HID-BPF is invoked.
Currently it implies a jmp table, a prog fd bpf_map, a preloaded tracing
bpf program and a lot of manual work for handling the bpf program
lifetime and addition/removal.

OTOH, bpf_struct_ops take care of most of the bpf handling leaving us
with a simple list of ops pointers, and we can directly call the
struct_ops program from the kernel as a regular function.

The net gain right now is in term of code simplicity and lines of code
removal (though is an API breakage), but udev-hid-bpf is able to handle
such breakages.

In the near future, we will be able to extend the HID-BPF struct_ops
with entrypoints for hid_hw_raw_request() and hid_hw_output_report(),
allowing for covering all of the initial use cases:
- firewalling a HID device
- fixing all of the HID device interactions (not just device events as
it is right now).

The matching user-space loader (udev-hid-bpf) MR is at
https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/86

I'll put it out of draft once this is merged.

Cheers,
Benjamin

Signed-off-by: Benjamin Tissoires <[email protected]>
---
Changes in v2:
- drop HID_BPF_FLAGS enum and use BPF_F_BEFORE instead
- fix .init_members to not open code member->offset
- allow struct hid_device to be writeable from HID-BPF for its name,
uniq and phys
- Link to v1: https://lore.kernel.org/r/[email protected]

---
Benjamin Tissoires (16):
HID: rename struct hid_bpf_ops into hid_ops
HID: bpf: add hid_get/put_device() helpers
HID: bpf: implement HID-BPF through bpf_struct_ops
selftests/hid: convert the hid_bpf selftests with struct_ops
HID: samples: convert the 2 HID-BPF samples into struct_ops
HID: bpf: add defines for HID-BPF SEC in in-tree bpf fixes
HID: bpf: convert in-tree fixes into struct_ops
HID: bpf: remove tracing HID-BPF capability
selftests/hid: add subprog call test
Documentation: HID: amend HID-BPF for struct_ops
Documentation: HID: add a small blurb on udev-hid-bpf
HID: bpf: Artist24: remove unused variable
HID: bpf: error on warnings when compiling bpf objects
bpf: allow bpf helpers to be used into HID-BPF struct_ops
HID: bpf: rework hid_bpf_ops_btf_struct_access
HID: bpf: make part of struct hid_device writable

Documentation/hid/hid-bpf.rst | 173 ++++---
drivers/hid/bpf/Makefile | 2 +-
drivers/hid/bpf/entrypoints/Makefile | 93 ----
drivers/hid/bpf/entrypoints/README | 4 -
drivers/hid/bpf/entrypoints/entrypoints.bpf.c | 25 -
drivers/hid/bpf/entrypoints/entrypoints.lskel.h | 248 ---------
drivers/hid/bpf/hid_bpf_dispatch.c | 266 +++-------
drivers/hid/bpf/hid_bpf_dispatch.h | 12 +-
drivers/hid/bpf/hid_bpf_jmp_table.c | 565 ---------------------
drivers/hid/bpf/hid_bpf_struct_ops.c | 298 +++++++++++
drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c | 9 +-
drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c | 6 +-
drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c | 9 +-
.../hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c | 6 +-
drivers/hid/bpf/progs/Makefile | 2 +-
.../hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c | 6 +-
drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c | 6 +-
drivers/hid/bpf/progs/XPPen__Artist24.bpf.c | 10 +-
drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c | 24 +-
drivers/hid/bpf/progs/hid_bpf.h | 5 +
drivers/hid/hid-core.c | 6 +-
include/linux/hid_bpf.h | 125 ++---
samples/hid/Makefile | 5 +-
samples/hid/hid_bpf_attach.bpf.c | 18 -
samples/hid/hid_bpf_attach.h | 14 -
samples/hid/hid_mouse.bpf.c | 26 +-
samples/hid/hid_mouse.c | 39 +-
samples/hid/hid_surface_dial.bpf.c | 10 +-
samples/hid/hid_surface_dial.c | 53 +-
tools/testing/selftests/hid/hid_bpf.c | 100 +++-
tools/testing/selftests/hid/progs/hid.c | 100 +++-
.../testing/selftests/hid/progs/hid_bpf_helpers.h | 19 +-
32 files changed, 805 insertions(+), 1479 deletions(-)
---
base-commit: 70ec81c2e2b4005465ad0d042e90b36087c36104
change-id: 20240513-hid_bpf_struct_ops-e3212a224555

Best regards,
--
Benjamin Tissoires <[email protected]>



2024-06-07 15:36:12

by Benjamin Tissoires

[permalink] [raw]
Subject: [PATCH HID v2 05/16] HID: samples: convert the 2 HID-BPF samples into struct_ops

This is mostly mechanical: attach_prog is dropped, and
the SEC are converted into struct_ops.

Signed-off-by: Benjamin Tissoires <[email protected]>

---

no changes in v2 but the commit message.
---
samples/hid/Makefile | 5 ++--
samples/hid/hid_bpf_attach.bpf.c | 18 -------------
samples/hid/hid_bpf_attach.h | 14 ----------
samples/hid/hid_mouse.bpf.c | 26 +++++++++++++++----
samples/hid/hid_mouse.c | 39 ++++++++--------------------
samples/hid/hid_surface_dial.bpf.c | 10 +++++--
samples/hid/hid_surface_dial.c | 53 +++++++++++---------------------------
7 files changed, 57 insertions(+), 108 deletions(-)

diff --git a/samples/hid/Makefile b/samples/hid/Makefile
index c128ccd49974..8ea59e9631a3 100644
--- a/samples/hid/Makefile
+++ b/samples/hid/Makefile
@@ -16,7 +16,6 @@ LIBBPF_DESTDIR = $(LIBBPF_OUTPUT)
LIBBPF_INCLUDE = $(LIBBPF_DESTDIR)/include
LIBBPF = $(LIBBPF_OUTPUT)/libbpf.a

-EXTRA_HEADERS := hid_bpf_attach.h
EXTRA_BPF_HEADERS := hid_bpf_helpers.h

hid_mouse-objs := hid_mouse.o
@@ -207,8 +206,8 @@ $(obj)/%.bpf.o: $(src)/%.bpf.c $(EXTRA_BPF_HEADERS_SRC) $(obj)/vmlinux.h
LINKED_SKELS := hid_mouse.skel.h hid_surface_dial.skel.h
clean-files += $(LINKED_SKELS)

-hid_mouse.skel.h-deps := hid_mouse.bpf.o hid_bpf_attach.bpf.o
-hid_surface_dial.skel.h-deps := hid_surface_dial.bpf.o hid_bpf_attach.bpf.o
+hid_mouse.skel.h-deps := hid_mouse.bpf.o
+hid_surface_dial.skel.h-deps := hid_surface_dial.bpf.o

LINKED_BPF_SRCS := $(patsubst %.bpf.o,%.bpf.c,$(foreach skel,$(LINKED_SKELS),$($(skel)-deps)))

diff --git a/samples/hid/hid_bpf_attach.bpf.c b/samples/hid/hid_bpf_attach.bpf.c
deleted file mode 100644
index d4dce4ea7c6e..000000000000
--- a/samples/hid/hid_bpf_attach.bpf.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2022 Benjamin Tissoires
- */
-
-#include "vmlinux.h"
-#include <bpf/bpf_helpers.h>
-#include <bpf/bpf_tracing.h>
-#include "hid_bpf_attach.h"
-#include "hid_bpf_helpers.h"
-
-SEC("syscall")
-int attach_prog(struct attach_prog_args *ctx)
-{
- ctx->retval = hid_bpf_attach_prog(ctx->hid,
- ctx->prog_fd,
- 0);
- return 0;
-}
diff --git a/samples/hid/hid_bpf_attach.h b/samples/hid/hid_bpf_attach.h
deleted file mode 100644
index 35bb28b49264..000000000000
--- a/samples/hid/hid_bpf_attach.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2022 Benjamin Tissoires
- */
-
-#ifndef __HID_BPF_ATTACH_H
-#define __HID_BPF_ATTACH_H
-
-struct attach_prog_args {
- int prog_fd;
- unsigned int hid;
- int retval;
-};
-
-#endif /* __HID_BPF_ATTACH_H */
diff --git a/samples/hid/hid_mouse.bpf.c b/samples/hid/hid_mouse.bpf.c
index 7c8b453ccb16..bd901fa855c9 100644
--- a/samples/hid/hid_mouse.bpf.c
+++ b/samples/hid/hid_mouse.bpf.c
@@ -5,8 +5,7 @@
#include <bpf/bpf_tracing.h>
#include "hid_bpf_helpers.h"

-SEC("fmod_ret/hid_bpf_device_event")
-int BPF_PROG(hid_y_event, struct hid_bpf_ctx *hctx)
+static int hid_y_event(struct hid_bpf_ctx *hctx)
{
s16 y;
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
@@ -51,8 +50,7 @@ int BPF_PROG(hid_y_event, struct hid_bpf_ctx *hctx)
return 0;
}

-SEC("fmod_ret/hid_bpf_device_event")
-int BPF_PROG(hid_x_event, struct hid_bpf_ctx *hctx)
+static int hid_x_event(struct hid_bpf_ctx *hctx)
{
s16 x;
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
@@ -69,7 +67,19 @@ int BPF_PROG(hid_x_event, struct hid_bpf_ctx *hctx)
return 0;
}

-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC("struct_ops/device_event")
+int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx, enum hid_report_type type)
+{
+ int ret = hid_y_event(hctx);
+
+ if (ret)
+ return ret;
+
+ return hid_x_event(hctx);
+}
+
+
+SEC("struct_ops/rdesc_fixup")
int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
@@ -109,4 +119,10 @@ int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
return 0;
}

+SEC(".struct_ops.link")
+struct hid_bpf_ops mouse_invert = {
+ .rdesc_fixup = (void *)hid_rdesc_fixup,
+ .device_event = (void *)hid_event,
+};
+
char _license[] SEC("license") = "GPL";
diff --git a/samples/hid/hid_mouse.c b/samples/hid/hid_mouse.c
index 018f1185f203..4b80d4e4c154 100644
--- a/samples/hid/hid_mouse.c
+++ b/samples/hid/hid_mouse.c
@@ -29,7 +29,6 @@
#include <bpf/libbpf.h>

#include "hid_mouse.skel.h"
-#include "hid_bpf_attach.h"

static bool running = true;

@@ -76,18 +75,11 @@ static int get_hid_id(const char *path)
int main(int argc, char **argv)
{
struct hid_mouse *skel;
- struct bpf_program *prog;
+ struct bpf_link *link;
int err;
const char *optstr = "";
const char *sysfs_path;
- int opt, hid_id, attach_fd;
- struct attach_prog_args args = {
- .retval = -1,
- };
- DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattr,
- .ctx_in = &args,
- .ctx_size_in = sizeof(args),
- );
+ int opt, hid_id;

while ((opt = getopt(argc, argv, optstr)) != -1) {
switch (opt) {
@@ -108,7 +100,7 @@ int main(int argc, char **argv)
return 1;
}

- skel = hid_mouse__open_and_load();
+ skel = hid_mouse__open();
if (!skel) {
fprintf(stderr, "%s %s:%d", __func__, __FILE__, __LINE__);
return -1;
@@ -120,27 +112,18 @@ int main(int argc, char **argv)
fprintf(stderr, "can not open HID device: %m\n");
return 1;
}
- args.hid = hid_id;
+ skel->struct_ops.mouse_invert->hid_id = hid_id;

- attach_fd = bpf_program__fd(skel->progs.attach_prog);
- if (attach_fd < 0) {
- fprintf(stderr, "can't locate attach prog: %m\n");
+ err = hid_mouse__load(skel);
+ if (err < 0) {
+ fprintf(stderr, "can not load HID-BPF program: %m\n");
return 1;
}

- bpf_object__for_each_program(prog, *skel->skeleton->obj) {
- /* ignore syscalls */
- if (bpf_program__get_type(prog) != BPF_PROG_TYPE_TRACING)
- continue;
-
- args.retval = -1;
- args.prog_fd = bpf_program__fd(prog);
- err = bpf_prog_test_run_opts(attach_fd, &tattr);
- if (err) {
- fprintf(stderr, "can't attach prog to hid device %d: %m (err: %d)\n",
- hid_id, err);
- return 1;
- }
+ link = bpf_map__attach_struct_ops(skel->maps.mouse_invert);
+ if (!link) {
+ fprintf(stderr, "can not attach HID-BPF program: %m\n");
+ return 1;
}

signal(SIGINT, int_exit);
diff --git a/samples/hid/hid_surface_dial.bpf.c b/samples/hid/hid_surface_dial.bpf.c
index 1f80478c0918..d8d0fb07391f 100644
--- a/samples/hid/hid_surface_dial.bpf.c
+++ b/samples/hid/hid_surface_dial.bpf.c
@@ -10,7 +10,7 @@
#define HID_UP_BUTTON 0x0009
#define HID_GD_WHEEL 0x0038

-SEC("fmod_ret/hid_bpf_device_event")
+SEC("struct_ops/device_event")
int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
@@ -101,7 +101,7 @@ int set_haptic(struct haptic_syscall_args *args)
}

/* Convert REL_DIAL into REL_WHEEL */
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC("struct_ops/rdesc_fixup")
int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
@@ -130,5 +130,11 @@ int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
return 0;
}

+SEC(".struct_ops.link")
+struct hid_bpf_ops surface_dial = {
+ .rdesc_fixup = (void *)hid_rdesc_fixup,
+ .device_event = (void *)hid_event,
+};
+
char _license[] SEC("license") = "GPL";
u32 _version SEC("version") = 1;
diff --git a/samples/hid/hid_surface_dial.c b/samples/hid/hid_surface_dial.c
index 4bc97373a708..9dd363845a85 100644
--- a/samples/hid/hid_surface_dial.c
+++ b/samples/hid/hid_surface_dial.c
@@ -31,7 +31,6 @@
#include <bpf/libbpf.h>

#include "hid_surface_dial.skel.h"
-#include "hid_bpf_attach.h"

static bool running = true;

@@ -86,34 +85,6 @@ static int get_hid_id(const char *path)
return (int)strtol(str_id, NULL, 16);
}

-static int attach_prog(struct hid_surface_dial *skel, struct bpf_program *prog, int hid_id)
-{
- struct attach_prog_args args = {
- .hid = hid_id,
- .retval = -1,
- };
- int attach_fd, err;
- DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattr,
- .ctx_in = &args,
- .ctx_size_in = sizeof(args),
- );
-
- attach_fd = bpf_program__fd(skel->progs.attach_prog);
- if (attach_fd < 0) {
- fprintf(stderr, "can't locate attach prog: %m\n");
- return 1;
- }
-
- args.prog_fd = bpf_program__fd(prog);
- err = bpf_prog_test_run_opts(attach_fd, &tattr);
- if (err) {
- fprintf(stderr, "can't attach prog to hid device %d: %m (err: %d)\n",
- hid_id, err);
- return 1;
- }
- return 0;
-}
-
static int set_haptic(struct hid_surface_dial *skel, int hid_id)
{
struct haptic_syscall_args args = {
@@ -144,10 +115,10 @@ static int set_haptic(struct hid_surface_dial *skel, int hid_id)
int main(int argc, char **argv)
{
struct hid_surface_dial *skel;
- struct bpf_program *prog;
const char *optstr = "r:";
+ struct bpf_link *link;
const char *sysfs_path;
- int opt, hid_id, resolution = 72;
+ int err, opt, hid_id, resolution = 72;

while ((opt = getopt(argc, argv, optstr)) != -1) {
switch (opt) {
@@ -189,7 +160,7 @@ int main(int argc, char **argv)
return 1;
}

- skel = hid_surface_dial__open_and_load();
+ skel = hid_surface_dial__open();
if (!skel) {
fprintf(stderr, "%s %s:%d", __func__, __FILE__, __LINE__);
return -1;
@@ -201,15 +172,21 @@ int main(int argc, char **argv)
return 1;
}

+ skel->struct_ops.surface_dial->hid_id = hid_id;
+
+ err = hid_surface_dial__load(skel);
+ if (err < 0) {
+ fprintf(stderr, "can not load HID-BPF program: %m\n");
+ return 1;
+ }
+
skel->data->resolution = resolution;
skel->data->physical = (int)(resolution / 72);

- bpf_object__for_each_program(prog, *skel->skeleton->obj) {
- /* ignore syscalls */
- if (bpf_program__get_type(prog) != BPF_PROG_TYPE_TRACING)
- continue;
-
- attach_prog(skel, prog, hid_id);
+ link = bpf_map__attach_struct_ops(skel->maps.surface_dial);
+ if (!link) {
+ fprintf(stderr, "can not attach HID-BPF program: %m\n");
+ return 1;
}

signal(SIGINT, int_exit);

--
2.44.0


2024-06-07 15:36:34

by Benjamin Tissoires

[permalink] [raw]
Subject: [PATCH HID v2 06/16] HID: bpf: add defines for HID-BPF SEC in in-tree bpf fixes

We are going to switch over struct_ops, so instead of having to manually
replace all fields one by one, let's have a common place to change it.

Signed-off-by: Benjamin Tissoires <[email protected]>

---

no changes in v2
---
drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c | 4 ++--
drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c | 2 +-
drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c | 4 ++--
drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c | 2 +-
drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c | 2 +-
drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c | 2 +-
drivers/hid/bpf/progs/XPPen__Artist24.bpf.c | 4 ++--
drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c | 6 +++---
drivers/hid/bpf/progs/hid_bpf.h | 3 +++
9 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c b/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c
index dc26a7677d36..2c2c1637ade8 100644
--- a/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c
+++ b/drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c
@@ -133,7 +133,7 @@ HID_BPF_CONFIG(
* integer. We thus divide it by 30 to match what other joysticks are
* doing
*/
-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
int BPF_PROG(hid_fix_rdesc_raptor_mach_2, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
@@ -152,7 +152,7 @@ int BPF_PROG(hid_fix_rdesc_raptor_mach_2, struct hid_bpf_ctx *hctx)
* divide it by 30.
* Byte 34 is always null, so it is ignored.
*/
-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
int BPF_PROG(raptor_mach_2_fix_hat_switch, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 64 /* size */);
diff --git a/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c b/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c
index 3d14bbb6f276..17fc55f6f02c 100644
--- a/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c
+++ b/drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c
@@ -30,7 +30,7 @@ HID_BPF_CONFIG(
* pointer.
*/

-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
diff --git a/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c b/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c
index ff759f2276f9..24b8a5aa05f3 100644
--- a/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c
+++ b/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c
@@ -191,7 +191,7 @@ static const __u8 fixed_rdesc[] = {
0xc0, // End Collection 327
};

-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
int BPF_PROG(hid_fix_rdesc_huion_kamvas_pro_19, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
@@ -215,7 +215,7 @@ int BPF_PROG(hid_fix_rdesc_huion_kamvas_pro_19, struct hid_bpf_ctx *hctx)
* - if there was this out-of-proximity event, we are entering
* eraser mode, and we will until the next out-of-proximity.
*/
-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
int BPF_PROG(kamvas_pro_19_fix_3rd_button, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
diff --git a/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c b/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c
index 225cbefdbf0e..bee37872ee8c 100644
--- a/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c
+++ b/drivers/hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c
@@ -21,7 +21,7 @@ HID_BPF_CONFIG(
* We just fix the report descriptor to enable those missing 7 buttons.
*/

-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
{
const u8 offsets[] = {84, 112, 140};
diff --git a/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c b/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c
index c04abecab8ee..f9ad33f4a373 100644
--- a/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c
+++ b/drivers/hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c
@@ -93,7 +93,7 @@ _Static_assert(sizeof(rdesc_assign_selection) == sizeof(fixed_rdesc_assign_selec
_Static_assert(sizeof(rdesc_assign_selection) + OFFSET_ASSIGN_SELECTION < ORIGINAL_RDESC_SIZE,
"Rdesc at given offset is too big");

-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
diff --git a/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c b/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
index dc05aa48faa7..39d77c5e9172 100644
--- a/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
+++ b/drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c
@@ -101,7 +101,7 @@ static inline __u8 *get_u8(__u8 *data, unsigned int offset)
return (__u8 *)get_bits(data, offset);
}

-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
int BPF_PROG(artpen_pressure_interpolate, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, PEN_REPORT_LEN /* size */);
diff --git a/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c b/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
index e1be6a12bb75..c938808bd589 100644
--- a/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
+++ b/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
@@ -91,7 +91,7 @@ static const __u8 fixed_rdesc[] = {

#define U16(index) (data[index] | (data[index + 1] << 8))

-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
int BPF_PROG(hid_fix_rdesc_xppen_artist24, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
@@ -152,7 +152,7 @@ static __u8 prev_state = 0;
* E: TipSwitch InRange
*
*/
-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
int BPF_PROG(xppen_24_fix_eraser, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
diff --git a/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c b/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c
index 65ef10036126..77ef8b95d52e 100644
--- a/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c
+++ b/drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c
@@ -82,7 +82,7 @@ static const __u8 fixed_rdesc[] = {
0xc0, // End Collection 112
};

-SEC("fmod_ret/hid_bpf_rdesc_fixup")
+SEC(HID_BPF_RDESC_FIXUP)
int BPF_PROG(hid_fix_rdesc_xppen_artistpro16gen2, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
@@ -105,7 +105,7 @@ int BPF_PROG(hid_fix_rdesc_xppen_artistpro16gen2, struct hid_bpf_ctx *hctx)
return sizeof(fixed_rdesc);
}

-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
int BPF_PROG(xppen_16_fix_eraser, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
@@ -207,7 +207,7 @@ static void compensate_coordinates_by_tilt(__u8 *data, const __u8 idx,
data[idx+1] = coords >> 8;
}

-SEC("fmod_ret/hid_bpf_device_event")
+SEC(HID_BPF_DEVICE_EVENT)
int BPF_PROG(xppen_16_fix_angle_offset, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
diff --git a/drivers/hid/bpf/progs/hid_bpf.h b/drivers/hid/bpf/progs/hid_bpf.h
index 7ee371cac2e1..1970faf84310 100644
--- a/drivers/hid/bpf/progs/hid_bpf.h
+++ b/drivers/hid/bpf/progs/hid_bpf.h
@@ -5,6 +5,9 @@
#ifndef ____HID_BPF__H
#define ____HID_BPF__H

+#define HID_BPF_DEVICE_EVENT "fmod_ret/hid_bpf_device_event"
+#define HID_BPF_RDESC_FIXUP "fmod_ret/hid_bpf_rdesc_fixup"
+
struct hid_bpf_probe_args {
unsigned int hid;
unsigned int rdesc_size;

--
2.44.0


2024-06-07 15:37:47

by Benjamin Tissoires

[permalink] [raw]
Subject: [PATCH HID v2 09/16] selftests/hid: add subprog call test

I got a weird verifier error with a subprog once, so let's have a test
for it.

Signed-off-by: Benjamin Tissoires <[email protected]>

---

no changes in v2
---
tools/testing/selftests/hid/hid_bpf.c | 41 +++++++++++++++++++++++++++++++++
tools/testing/selftests/hid/progs/hid.c | 24 +++++++++++++++++++
2 files changed, 65 insertions(+)

diff --git a/tools/testing/selftests/hid/hid_bpf.c b/tools/testing/selftests/hid/hid_bpf.c
index 967dfe6b58cb..45e173db35bd 100644
--- a/tools/testing/selftests/hid/hid_bpf.c
+++ b/tools/testing/selftests/hid/hid_bpf.c
@@ -638,6 +638,47 @@ TEST_F(hid_bpf, raw_event)
ASSERT_EQ(buf[2], 52);
}

+/*
+ * Attach hid_first_event to the given uhid device,
+ * retrieve and open the matching hidraw node,
+ * inject one event in the uhid device,
+ * check that the program sees it and can change the data
+ */
+TEST_F(hid_bpf, subprog_raw_event)
+{
+ const struct test_program progs[] = {
+ { .name = "hid_subprog_first_event" },
+ };
+ __u8 buf[10] = {0};
+ int err;
+
+ LOAD_PROGRAMS(progs);
+
+ /* inject one event */
+ buf[0] = 1;
+ buf[1] = 42;
+ uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+
+ /* read the data from hidraw */
+ memset(buf, 0, sizeof(buf));
+ err = read(self->hidraw_fd, buf, sizeof(buf));
+ ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
+ ASSERT_EQ(buf[0], 1);
+ ASSERT_EQ(buf[2], 47);
+
+ /* inject another event */
+ memset(buf, 0, sizeof(buf));
+ buf[0] = 1;
+ buf[1] = 47;
+ uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+
+ /* read the data from hidraw */
+ memset(buf, 0, sizeof(buf));
+ err = read(self->hidraw_fd, buf, sizeof(buf));
+ ASSERT_EQ(err, 6) TH_LOG("read_hidraw");
+ ASSERT_EQ(buf[2], 52);
+}
+
/*
* Ensures that we can attach/detach programs
*/
diff --git a/tools/testing/selftests/hid/progs/hid.c b/tools/testing/selftests/hid/progs/hid.c
index 614f1aa32649..2e7e5a736dc6 100644
--- a/tools/testing/selftests/hid/progs/hid.c
+++ b/tools/testing/selftests/hid/progs/hid.c
@@ -35,6 +35,30 @@ struct hid_bpf_ops first_event = {
.hid_id = 2,
};

+int __hid_subprog_first_event(struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
+{
+ __u8 *rw_data = hid_bpf_get_data(hid_ctx, 0 /* offset */, 3 /* size */);
+
+ if (!rw_data)
+ return 0; /* EPERM check */
+
+ rw_data[2] = rw_data[1] + 5;
+
+ return hid_ctx->size;
+}
+
+SEC("?struct_ops/hid_device_event")
+int BPF_PROG(hid_subprog_first_event, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
+{
+ return __hid_subprog_first_event(hid_ctx, type);
+}
+
+SEC(".struct_ops.link")
+struct hid_bpf_ops subprog_first_event = {
+ .hid_device_event = (void *)hid_subprog_first_event,
+ .hid_id = 2,
+};
+
SEC("?struct_ops/hid_device_event")
int BPF_PROG(hid_second_event, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
{

--
2.44.0


2024-06-07 15:38:10

by Benjamin Tissoires

[permalink] [raw]
Subject: [PATCH HID v2 10/16] Documentation: HID: amend HID-BPF for struct_ops

Now that we are using struct_ops, the docs need to be changed.

Signed-off-by: Benjamin Tissoires <[email protected]>

---

changes in v2
- use BPF_F_BEFORE
---
Documentation/hid/hid-bpf.rst | 156 +++++++++++++++++++-----------------------
include/linux/hid_bpf.h | 8 +--
2 files changed, 76 insertions(+), 88 deletions(-)

diff --git a/Documentation/hid/hid-bpf.rst b/Documentation/hid/hid-bpf.rst
index 0765b3298ecf..456e15097d87 100644
--- a/Documentation/hid/hid-bpf.rst
+++ b/Documentation/hid/hid-bpf.rst
@@ -132,16 +132,17 @@ input events.
Available types of programs
===========================

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

HID-BPF has the following attachment types available:

-1. event processing/filtering with ``SEC("fmod_ret/hid_bpf_device_event")`` in libbpf
+1. event processing/filtering with ``SEC("struct_ops/hid_device_event")`` in libbpf
2. actions coming from userspace with ``SEC("syscall")`` in libbpf
-3. change of the report descriptor with ``SEC("fmod_ret/hid_bpf_rdesc_fixup")`` in libbpf
+3. change of the report descriptor with ``SEC("struct_ops/hid_rdesc_fixup")`` or
+ ``SEC("struct_ops.s/hid_rdesc_fixup")`` in libbpf

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

@@ -149,37 +150,42 @@ A ``syscall`` means that userspace called the syscall ``BPF_PROG_RUN`` facility.
This time, we can do any operations allowed by HID-BPF, and talking to the device is
allowed.

-Last, ``hid_bpf_rdesc_fixup`` is different from the others as there can be only one
+Last, ``hid_rdesc_fixup`` is different from the others as there can be only one
BPF program of this type. This is called on ``probe`` from the driver and allows to
-change the report descriptor from the BPF program. Once a ``hid_bpf_rdesc_fixup``
+change the report descriptor from the BPF program. Once a ``hid_rdesc_fixup``
program has been loaded, it is not possible to overwrite it unless the program which
inserted it allows us by pinning the program and closing all of its fds pointing to it.

+Note that ``hid_rdesc_fixup`` can be declared as sleepable (``SEC("struct_ops.s/hid_rdesc_fixup")``).
+
+
Developer API:
==============

-User API data structures available in programs:
------------------------------------------------
+Available ``struct_ops`` for HID-BPF:
+-------------------------------------

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

-Available tracing functions to attach a HID-BPF program:
---------------------------------------------------------

-.. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c
- :functions: hid_bpf_device_event hid_bpf_rdesc_fixup
+User API data structures available in programs:
+-----------------------------------------------
+
+.. kernel-doc:: include/linux/hid_bpf.h
+ :identifiers: hid_bpf_ctx

-Available API that can be used in all HID-BPF programs:
--------------------------------------------------------
+Available API that can be used in all HID-BPF struct_ops programs:
+------------------------------------------------------------------

.. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c
- :functions: hid_bpf_get_data
+ :identifiers: hid_bpf_get_data

-Available API that can be used in syscall HID-BPF programs:
------------------------------------------------------------
+Available API that can be used in syscall HID-BPF programs or in sleepable HID-BPF struct_ops programs:
+-------------------------------------------------------------------------------------------------------

.. kernel-doc:: drivers/hid/bpf/hid_bpf_dispatch.c
- :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
+ :identifiers: hid_bpf_hw_request hid_bpf_hw_output_report hid_bpf_input_report hid_bpf_allocate_context hid_bpf_release_context

General overview of a HID-BPF program
=====================================
@@ -222,20 +228,21 @@ This allows the following:
Effect of a HID-BPF program
---------------------------

-For all HID-BPF attachment types except for :c:func:`hid_bpf_rdesc_fixup`, several eBPF
-programs can be attached to the same device.
+For all HID-BPF attachment types except for :c:func:`hid_rdesc_fixup`, several eBPF
+programs can be attached to the same device. If a HID-BPF struct_ops has a
+:c:func:`hid_rdesc_fixup` while another is already attached to the device, the
+kernel will return `-EINVAL` when attaching the struct_ops.

-Unless ``HID_BPF_FLAG_INSERT_HEAD`` is added to the flags while attaching the
-program, the new program is appended at the end of the list.
-``HID_BPF_FLAG_INSERT_HEAD`` will insert the new program at the beginning of the
-list which is useful for e.g. tracing where we need to get the unprocessed events
-from the device.
+Unless ``BPF_F_BEFORE`` is added to the flags while attaching the program, the new
+program is appended at the end of the list.
+``BPF_F_BEFORE`` will insert the new program at the beginning of the list which is
+useful for e.g. tracing where we need to get the unprocessed events from the device.

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

-``SEC("fmod_ret/hid_bpf_device_event")``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+``SEC("struct_ops/hid_device_event")``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

To retrieve a context associated with the device, the program must call
-:c:func:`hid_bpf_allocate_context` and must release it with :c:func:`hid_bpf_release_context`
+hid_bpf_allocate_context() and must release it with hid_bpf_release_context()
before returning.
Once the context is retrieved, one can also request a pointer to kernel memory with
-:c:func:`hid_bpf_get_data`. This memory is big enough to support all input/output/feature
+hid_bpf_get_data(). This memory is big enough to support all input/output/feature
reports of the given device.

-``SEC("fmod_ret/hid_bpf_rdesc_fixup")``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+``SEC("struct_ops/hid_rdesc_fixup")``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

-The ``hid_bpf_rdesc_fixup`` program works in a similar manner to
-``.report_fixup`` of ``struct hid_driver``.
+The ``hid_rdesc_fixup`` program works in a similar manner to ``.report_fixup``
+of ``struct hid_driver``.

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

-Whenever a ``SEC("fmod_ret/hid_bpf_rdesc_fixup")`` program is attached (if no
-program was attached before), the kernel immediately disconnects the HID device
-and does a reprobe.
+Whenever a struct_ops containing a ``SEC("struct_ops/hid_rdesc_fixup")`` program
+is attached (if no program was attached before), the kernel immediately disconnects
+the HID device and does a reprobe.

-In the same way, when the ``SEC("fmod_ret/hid_bpf_rdesc_fixup")`` program is
-detached, the kernel issues a disconnect on the device.
+In the same way, when this struct_ops is detached, the kernel issues a disconnect
+on the device.

There is no ``detach`` facility in HID-BPF. Detaching a program happens when
-all the user space file descriptors pointing at a program are closed.
+all the user space file descriptors pointing at a HID-BPF struct_ops link are closed.
Thus, if we need to replace a report descriptor fixup, some cooperation is
required from the owner of the original report descriptor fixup.
-The previous owner will likely pin the program in the bpffs, and we can then
+The previous owner will likely pin the struct_ops link in the bpffs, and we can then
replace it through normal bpf operations.

Attaching a bpf program to a device
===================================

-``libbpf`` does not export any helper to attach a HID-BPF program.
-Users need to use a dedicated ``syscall`` program which will call
-``hid_bpf_attach_prog(hid_id, program_fd, flags)``.
+We now use standard struct_ops attachment through ``bpf_map__attach_struct_ops()``.
+But given that we need to attach a struct_ops to a dedicated HID device, the caller
+must set ``hid_id`` in the struct_ops map before loading the program in the kernel.

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

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

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

struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 4096 * 64);
} ringbuf SEC(".maps");

- struct attach_prog_args {
- int prog_fd;
- unsigned int hid;
- unsigned int flags;
- int retval;
- };
-
- SEC("syscall")
- int attach_prog(struct attach_prog_args *ctx)
- {
- ctx->retval = hid_bpf_attach_prog(ctx->hid,
- ctx->prog_fd,
- ctx->flags);
- return 0;
- }
-
__u8 current_value = 0;

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

-To attach ``filter_switch``, userspace needs to call the ``attach_prog`` syscall
-program first::
+ SEC(".struct_ops.link")
+ struct hid_bpf_ops haptic_tablet = {
+ .hid_device_event = (void *)filter_switch,
+ };
+
+
+To attach ``haptic_tablet``, userspace needs to set ``hid_id`` first::

static int attach_filter(struct hid *hid_skel, int hid_id)
{
- int err, prog_fd;
- int ret = -1;
- struct attach_prog_args args = {
- .hid = hid_id,
- };
- DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattrs,
- .ctx_in = &args,
- .ctx_size_in = sizeof(args),
- );
+ int err, link_fd;

- args.prog_fd = bpf_program__fd(hid_skel->progs.filter_switch);
+ hid_skel->struct_ops.haptic_tablet->hid_id = hid_id;
+ err = hid__load(skel);
+ if (err)
+ return err;

- prog_fd = bpf_program__fd(hid_skel->progs.attach_prog);
-
- err = bpf_prog_test_run_opts(prog_fd, &tattrs);
- if (err)
- return err;
+ link_fd = bpf_map__attach_struct_ops(hid_skel->maps.haptic_tablet);
+ if (!link_fd) {
+ fprintf(stderr, "can not attach HID-BPF program: %m\n");
+ return -1;
+ }

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

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

When the userspace program doesn't need to listen to events anymore, it can just
-close the returned fd from :c:func:`attach_filter`, which will tell the kernel to
+close the returned bpf link from :c:func:`attach_filter`, which will tell the kernel to
detach the program from the HID device.

Of course, in other use cases, the userspace program can also pin the fd to the
diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h
index 06ce3d688915..88ab4925bdaa 100644
--- a/include/linux/hid_bpf.h
+++ b/include/linux/hid_bpf.h
@@ -20,11 +20,9 @@ struct hid_device;
* struct hid_bpf_ctx - User accessible data for all HID programs
*
* ``data`` is not directly accessible from the context. We need to issue
- * a call to ``hid_bpf_get_data()`` in order to get a pointer to that field.
+ * a call to hid_bpf_get_data() in order to get a pointer to that field.
*
- * All of these fields are currently read-only.
- *
- * @hid: the ``struct hid_device`` representing the device itself
+ * @hid: the &struct hid_device representing the device itself
* @allocated_size: Allocated size of data.
*
* This is how much memory is available and can be requested
@@ -41,6 +39,8 @@ struct hid_device;
* ``size`` must always be less or equal than ``allocated_size`` (it is enforced
* once all BPF programs have been run).
* @retval: Return value of the previous program.
+ *
+ * ``hid`` and ``allocated_size`` are read-only, ``size`` and ``retval`` are read-write.
*/
struct hid_bpf_ctx {
const struct hid_device *hid;

--
2.44.0


2024-06-07 15:38:48

by Benjamin Tissoires

[permalink] [raw]
Subject: [PATCH HID v2 12/16] HID: bpf: Artist24: remove unused variable

warning: unused variable ‘tilt’ [-Wunused-variable]

Signed-off-by: Peter Hutterer <[email protected]>
Signed-off-by: Benjamin Tissoires <[email protected]>

---

no changes in v2
---
drivers/hid/bpf/progs/XPPen__Artist24.bpf.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c b/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
index bc0b85c38445..d4d062c3a653 100644
--- a/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
+++ b/drivers/hid/bpf/progs/XPPen__Artist24.bpf.c
@@ -158,7 +158,6 @@ int BPF_PROG(xppen_24_fix_eraser, struct hid_bpf_ctx *hctx)
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
__u8 current_state, changed_state;
bool prev_tip;
- __u16 tilt;

if (!data)
return 0; /* EPERM check */

--
2.44.0


2024-06-07 15:39:59

by Benjamin Tissoires

[permalink] [raw]
Subject: [PATCH HID v2 16/16] HID: bpf: make part of struct hid_device writable

It is useful to change the name, the phys and/or the uniq of a
struct hid_device during .rdesc_fixup().

For example, hid-uclogic.ko changes the uniq to store the firmware version
to differentiate between 2 devices sharing the same PID. In the same
way, changing the device name is useful when the device export 3 nodes,
all with the same name.

Signed-off-by: Benjamin Tissoires <[email protected]>

---

new in v2
---
drivers/hid/bpf/hid_bpf_struct_ops.c | 3 +++
include/linux/hid_bpf.h | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/bpf/hid_bpf_struct_ops.c b/drivers/hid/bpf/hid_bpf_struct_ops.c
index 944e6d91a36b..14a4c64ae242 100644
--- a/drivers/hid/bpf/hid_bpf_struct_ops.c
+++ b/drivers/hid/bpf/hid_bpf_struct_ops.c
@@ -74,6 +74,9 @@ static int hid_bpf_ops_btf_struct_access(struct bpf_verifier_log *log,

const struct hid_bpf_offset_write_range write_ranges[] = {
WRITE_RANGE(hid_bpf_ctx, retval, 0, 0),
+ WRITE_RANGE(hid_device, name, 0, -1), /* minus 1 to ensure \0 at the end */
+ WRITE_RANGE(hid_device, uniq, 0, -1), /* minus 1 to ensure \0 at the end */
+ WRITE_RANGE(hid_device, phys, 0, -1), /* minus 1 to ensure \0 at the end */
};
#undef WRITE_RANGE
const struct btf_type *state = NULL;
diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h
index 88ab4925bdaa..ff30cbc0a090 100644
--- a/include/linux/hid_bpf.h
+++ b/include/linux/hid_bpf.h
@@ -43,7 +43,7 @@ struct hid_device;
* ``hid`` and ``allocated_size`` are read-only, ``size`` and ``retval`` are read-write.
*/
struct hid_bpf_ctx {
- const struct hid_device *hid;
+ struct hid_device *hid;
__u32 allocated_size;
union {
__s32 retval;

--
2.44.0