When I introduced HID-BPF, I mentioned that we should ship the HID-BPF
programs in the kernel when they are fixes so that everybody can benefit
from them.
I tried multiple times to do so but I was confronted to a tough problem:
how can I make the kernel load them automatically?
I went over a few solutions, but it always came down to something either
ugly, or either not satisfying (like forcing `bpftool` to be compiled
first, or not being able to insert them as a module).
OTOH, I was working with Peter on `udev-hid-bpf`[0] as a proof of
concept on how a minimal loader should look like. This allowed me to
experiment on the BPF files and how they should look like.
And after further thoughts, I realized that `udev-hid-bpf` could very
well be the `kmod load` that we currently have:
- the kernel handles the device normally
- a udev event is emitted
- a udev rule fires `udev-hid-bpf` and load the appropriate HID-BPF
file(s) based on the modalias
Given that most HID devices are supposed to work to a minimal level when
connected without any driver, this makes the whole HID-BPF programs nice
to have but not critical. We can then postpone the HID-BPF loading when
userspace is ready.
Working with HID-BPF is also a much better user experience for end users
(as I predicted). All they have to do is to go to the `udev-hid-bpf`
project, fetch an artifact from the MR that concerns them, run
`install.sh` (no compilation required), and their devices are fixed
(minus some back and forth when the HID-BPF program needs some changes).
So I already have that loader available, and it works well enough for
our users. But the missing point was still how to "upstream" those BPF
fixes?
That's where this patch series comes in: we simply store the fixes in
the kernel under `drivers/hid/bpf/progs`, provide a way to compile them,
but also add tests for them in the selftests dir.
Once a program is accepted here, for convenience, the same program will
move from a "testing" directory to a "stable" directory on
`udev-hid-bpf`. This way, distributions don't need to follow when there
is a new program added here, they can just ship the "stable" ones from
`udev-hid-bpf`.
Signed-off-by: Benjamin Tissoires <bentiss(a)kernel.org>
[0] https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/
---
Benjamin Tissoires (18):
HID: do not assume HAT Switch logical max < 8
HID: bpf: add first in-tree HID-BPF fix for the XPPen Artist 24
HID: bpf: add in-tree HID-BPF fix for the XPPen Artist 16
HID: bpf: add in-tree HID-BPF fix for the HP Elite Presenter Mouse
HID: bpf: add in-tree HID-BPF fix for the IOGear Kaliber Gaming MMOmentum mouse
HID: bpf: add in-tree HID-BPF fix for the Wacom ArtPen
HID: bpf: add in-tree HID-BPF fix for the XBox Elite 2 over Bluetooth
HID: bpf: add in-tree HID-BPF fix for the Huion Kamvas Pro 19
HID: bpf: add in-tree HID-BPF fix for the Raptor Mach 2
selftests/hid: import base_device.py from hid-tools
selftests/hid: add support for HID-BPF pre-loading before starting a test
selftests/hid: tablets: reduce the number of pen state
selftests/hid: tablets: add a couple of XP-PEN tablets
selftests/hid: tablets: also check for XP-Pen offset correction
selftests/hid: add Huion Kamvas Pro 19 tests
selftests/hid: import base_gamepad.py from hid-tools
selftests/hid: move the gamepads definitions in the test file
selftests/hid: add tests for the Raptor Mach 2 joystick
drivers/hid/bpf/progs/FR-TEC__Raptor-Mach-2.bpf.c | 185 ++++++
drivers/hid/bpf/progs/HP__Elite-Presenter.bpf.c | 58 ++
drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c | 290 +++++++++
.../hid/bpf/progs/IOGEAR__Kaliber-MMOmentum.bpf.c | 59 ++
drivers/hid/bpf/progs/Makefile | 91 +++
.../hid/bpf/progs/Microsoft__XBox-Elite-2.bpf.c | 133 ++++
drivers/hid/bpf/progs/README | 102 +++
drivers/hid/bpf/progs/Wacom__ArtPen.bpf.c | 173 +++++
drivers/hid/bpf/progs/XPPen__Artist24.bpf.c | 229 +++++++
drivers/hid/bpf/progs/XPPen__ArtistPro16Gen2.bpf.c | 274 ++++++++
drivers/hid/bpf/progs/hid_bpf.h | 15 +
drivers/hid/bpf/progs/hid_bpf_helpers.h | 170 +++++
include/linux/hid.h | 6 +-
tools/testing/selftests/hid/tests/base.py | 87 ++-
tools/testing/selftests/hid/tests/base_device.py | 421 ++++++++++++
tools/testing/selftests/hid/tests/base_gamepad.py | 238 +++++++
tools/testing/selftests/hid/tests/test_gamepad.py | 457 ++++++++++++-
tools/testing/selftests/hid/tests/test_tablet.py | 723 +++++++++++++++------
18 files changed, 3507 insertions(+), 204 deletions(-)
---
base-commit: 3e78a6c0d3e02e4cf881dc84c5127e9990f939d6
change-id: 20240328-bpf_sources-be1f3c617c5e
Best regards,
--
Benjamin Tissoires <bentiss(a)kernel.org>
Add several new test cases which assert corner cases on the eventfd
mechanism, for example, the supplied buffer is less than 8 bytes,
attempting to write a value that is too large, etc.
./eventfd_test
# Starting 9 tests from 1 test cases.
# RUN global.eventfd01 ...
# OK global.eventfd01
ok 1 global.eventfd01
# RUN global.eventfd02 ...
# OK global.eventfd02
ok 2 global.eventfd02
# RUN global.eventfd03 ...
# OK global.eventfd03
ok 3 global.eventfd03
# RUN global.eventfd04 ...
# OK global.eventfd04
ok 4 global.eventfd04
# RUN global.eventfd05 ...
# OK global.eventfd05
ok 5 global.eventfd05
# RUN global.eventfd06 ...
# OK global.eventfd06
ok 6 global.eventfd06
# RUN global.eventfd07 ...
# OK global.eventfd07
ok 7 global.eventfd07
# RUN global.eventfd08 ...
# OK global.eventfd08
ok 8 global.eventfd08
# RUN global.eventfd09 ...
# OK global.eventfd09
ok 9 global.eventfd09
# PASSED: 9 / 9 tests passed.
# Totals: pass:9 fail:0 xfail:0 xpass:0 skip:0 error:0
Signed-off-by: Wen Yang <wen.yang(a)linux.dev>
Cc: SShuah Khan <shuah(a)kernel.org>
Cc: Christian Brauner <brauner(a)kernel.org>
Cc: Andrei Vagin <avagin(a)google.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers(a)efficios.com>
Cc: Steven Rostedt <rostedt(a)goodmis.org>
Cc: Andrew Morton <akpm(a)linux-foundation.org>
Cc: Dave Young <dyoung(a)redhat.com>
Cc: linux-kselftest(a)vger.kernel.org
Cc: linux-kernel(a)vger.kernel.org
---
.../filesystems/eventfd/eventfd_test.c | 116 ++++++++++++++++++
1 file changed, 116 insertions(+)
diff --git a/tools/testing/selftests/filesystems/eventfd/eventfd_test.c b/tools/testing/selftests/filesystems/eventfd/eventfd_test.c
index f142a137526c..eeab8df5b1b5 100644
--- a/tools/testing/selftests/filesystems/eventfd/eventfd_test.c
+++ b/tools/testing/selftests/filesystems/eventfd/eventfd_test.c
@@ -183,4 +183,120 @@ TEST(eventfd05)
close(fd);
}
+/*
+ * A write(2) fails with the error EINVAL if the size of the supplied buffer
+ * is less than 8 bytes, or if an attempt is made to write the value
+ * 0xffffffffffffffff.
+ */
+TEST(eventfd06)
+{
+ uint64_t value = 1;
+ ssize_t size;
+ int fd;
+
+ fd = sys_eventfd2(0, 0);
+ ASSERT_GE(fd, 0);
+
+ size = write(fd, &value, sizeof(int));
+ EXPECT_EQ(size, -1);
+ EXPECT_EQ(errno, EINVAL);
+
+ value = (uint64_t)-1;
+ size = write(fd, &value, sizeof(value));
+ EXPECT_EQ(size, -1);
+ EXPECT_EQ(errno, EINVAL);
+
+ close(fd);
+}
+
+/*
+ * A read(2) fails with the error EINVAL if the size of the supplied buffer is
+ * less than 8 bytes.
+ */
+TEST(eventfd07)
+{
+ int value = 0;
+ ssize_t size;
+ int fd;
+
+ fd = sys_eventfd2(0, 0);
+ ASSERT_GE(fd, 0);
+
+ size = write(fd, &value, sizeof(value));
+ EXPECT_EQ(size, -1);
+ EXPECT_EQ(errno, EINVAL);
+
+ close(fd);
+}
+
+/*
+ * If EFD_SEMAPHORE was not specified and the eventfd counter has a nonzero
+ * value, then a read(2) returns 8 bytes containing that value, and the
+ * counter's value is reset to zero.
+ * If the eventfd counter is zero at the time of the call to read(2), then the
+ * call fails with the error EAGAIN if the file descriptor has been made nonblocking.
+ */
+TEST(eventfd08)
+{
+ uint64_t value;
+ ssize_t size;
+ int fd;
+ int i;
+
+ fd = sys_eventfd2(0, EFD_NONBLOCK);
+ ASSERT_GE(fd, 0);
+
+ value = 1;
+ for (i = 0; i < 10000000; i++) {
+ size = write(fd, &value, sizeof(value));
+ EXPECT_EQ(size, sizeof(value));
+ }
+
+ size = read(fd, &value, sizeof(value));
+ EXPECT_EQ(size, sizeof(uint64_t));
+ EXPECT_EQ(value, 10000000);
+
+ size = read(fd, &value, sizeof(value));
+ EXPECT_EQ(size, -1);
+ EXPECT_EQ(errno, EAGAIN);
+
+ close(fd);
+}
+
+/*
+ * If EFD_SEMAPHORE was specified and the eventfd counter has a nonzero value,
+ * then a read(2) returns 8 bytes containing the value 1, and the counter's
+ * value is decremented by 1.
+ * If the eventfd counter is zero at the time of the call to read(2), then the
+ * call fails with the error EAGAIN if the file descriptor has been made nonblocking.
+ */
+TEST(eventfd09)
+{
+ uint64_t value;
+ ssize_t size;
+ int fd;
+ int i;
+
+ fd = sys_eventfd2(0, EFD_SEMAPHORE|EFD_NONBLOCK);
+ ASSERT_GE(fd, 0);
+
+ value = 1;
+ for (i = 0; i < 10000000; i++) {
+ size = write(fd, &value, sizeof(value));
+ EXPECT_EQ(size, sizeof(value));
+ }
+
+ for (i = 0; i < 10000000; i++) {
+ size = read(fd, &value, sizeof(value));
+ EXPECT_EQ(size, sizeof(value));
+ EXPECT_EQ(value, 1);
+ }
+
+ size = read(fd, &value, sizeof(value));
+ EXPECT_EQ(size, -1);
+ EXPECT_EQ(errno, EAGAIN);
+
+ close(fd);
+}
+
TEST_HARNESS_MAIN
--
2.25.1
This is a RFC, following[0].
It works, still needs some care but this is mainly to see if this will
have a chance to get upsrteamed or if I should rely on struct_ops
instead.
Cheers,
Benjamin
Signed-off-by: Benjamin Tissoires <bentiss(a)kernel.org>
---
Benjamin Tissoires (8):
bpf: ignore sleepable prog parameter for kfuncs
bpf: add kfunc_meta parameter to push_callback_call()
bpf: implement __async and __s_async kfunc suffixes
bpf: typedef a type for the bpf_wq callbacks
selftests/bpf: rely on wq_callback_fn_t
bpf: remove one special case of is_bpf_wq_set_callback_impl_kfunc
bpf: implement __aux kfunc argument suffix to fetch prog_aux
bpf: rely on __aux suffix for bpf_wq_set_callback_impl
kernel/bpf/helpers.c | 10 +-
kernel/bpf/verifier.c | 333 +++++++++++++++++++-----
tools/testing/selftests/bpf/bpf_experimental.h | 3 +-
tools/testing/selftests/bpf/progs/wq.c | 10 +-
tools/testing/selftests/bpf/progs/wq_failures.c | 4 +-
5 files changed, 280 insertions(+), 80 deletions(-)
---
base-commit: 05cbc217aafbc631a6c2fab4accf95850cb48358
change-id: 20240507-bpf_async-bd2e65847525
Best regards,
--
Benjamin Tissoires <bentiss(a)kernel.org>
Hi,
This fix, originally intended for XFRM/IPsec, has been recommended by
Steffen Klassert to submit to the net tree.
The patch addresses a minor issue related to the IPv4 source address of
ICMP error messages, which originated from an old 2011 commit:
415b3334a21a ("icmp: Fix regression in nexthop resolution during replies.")
The omission of a "Fixes" tag in the following commit is deliberate
to prevent potential test failures and subsequent regression issues
that may arise from backporting this patch all stable kerenels.
This is a minor fix, anot not security fix.
With a seleftest I am submitting this to net-next tree.
v2->v3 : fix testscript. The IFS, space, got mangled.
v1->v2 : add kernel selftest script
Antony Antony (2):
xfrm: fix source address in icmp error generation from IPsec gateway
selftests/net: add ICMP unreachable over IPsec tunnel
net/ipv4/icmp.c | 1 -
tools/testing/selftests/net/Makefile | 1 +
tools/testing/selftests/net/xfrm_state.sh | 624 ++++++++++++++++++++++
3 files changed, 625 insertions(+), 1 deletion(-)
create mode 100755 tools/testing/selftests/net/xfrm_state.sh
--
2.30.2
Cast operation has a higher precedence than addition. The code here
wants to zero the 2nd half of the 64-bit metadata, but due to a pointer
arithmetic mistake, it writes the zero at offset 16 instead.
Just adding parentheses around "data + 4" would fix this, but I think
this will be slightly better readable with array syntax.
I was unable to test this with tools/testing/selftests/bpf/vmtest.sh,
because my glibc is newer than glibc in the provided VM image.
So I just checked the difference in the compiled code.
objdump -S tools/testing/selftests/bpf/xdp_do_redirect.test.o:
- *((__u32 *)data) = 0x42; /* metadata test value */
+ ((__u32 *)data)[0] = 0x42; /* metadata test value */
be7: 48 8d 85 30 fc ff ff lea -0x3d0(%rbp),%rax
bee: c7 00 42 00 00 00 movl $0x42,(%rax)
- *((__u32 *)data + 4) = 0;
+ ((__u32 *)data)[1] = 0;
bf4: 48 8d 85 30 fc ff ff lea -0x3d0(%rbp),%rax
- bfb: 48 83 c0 10 add $0x10,%rax
+ bfb: 48 83 c0 04 add $0x4,%rax
bff: c7 00 00 00 00 00 movl $0x0,(%rax)
Fixes: 5640b6d89434 ("selftests/bpf: fix "metadata marker" getting overwritten by the netstack")
Signed-off-by: Michal Schmidt <mschmidt(a)redhat.com>
---
tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c b/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c
index 498d3bdaa4b0..bad0ea167be7 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c
@@ -107,8 +107,8 @@ void test_xdp_do_redirect(void)
.attach_point = BPF_TC_INGRESS);
memcpy(&data[sizeof(__u64)], &pkt_udp, sizeof(pkt_udp));
- *((__u32 *)data) = 0x42; /* metadata test value */
- *((__u32 *)data + 4) = 0;
+ ((__u32 *)data)[0] = 0x42; /* metadata test value */
+ ((__u32 *)data)[1] = 0;
skel = test_xdp_do_redirect__open();
if (!ASSERT_OK_PTR(skel, "skel"))
--
2.44.0
From: Geliang Tang <tanggeliang(a)kylinos.cn>
v4:
- fix a bug in v3, it should be 'if (err)', not 'if (!err)'.
- move "selftests/bpf: Use log_err in network_helpers" out of this
series.
v3:
- add two more patches.
- use log_err instead of ASSERT in v3.
- let send_recv_data return int as Martin suggested.
v2:
Address Martin's comments for v1 (thanks.)
- drop patch 1, "export send_byte helper".
- drop "WRITE_ONCE(arg.stop, 0)".
- rebased.
send_recv_data will be re-used in MPTCP bpf tests, but not included
in this set because it depends on other patches that have not been
in the bpf-next yet. It will be sent as another set soon.
Geliang Tang (3):
selftests/bpf: Add struct send_recv_arg
selftests/bpf: Export send_recv_data helper
selftests/bpf: Support nonblock for send_recv_data
tools/testing/selftests/bpf/network_helpers.c | 103 ++++++++++++++++++
tools/testing/selftests/bpf/network_helpers.h | 1 +
.../selftests/bpf/prog_tests/bpf_tcp_ca.c | 71 +-----------
3 files changed, 105 insertions(+), 70 deletions(-)
--
2.40.1
Fixes clang compilation warnings by adding explicit unsigned conversion:
parse_vdso.c:206:22: warning: passing 'const char *' to parameter of
type 'const unsigned char *' converts between pointers to integer types
where one is of the unique plain 'char' type and the other is not
[-Wpointer-sign]
ver_hash = elf_hash(version);
^~~~~~~
parse_vdso.c:59:52: note: passing argument to parameter 'name' here
static unsigned long elf_hash(const unsigned char *name)
^
parse_vdso.c:207:46: warning: passing 'const char *' to parameter of
type 'const unsigned char *' converts between pointers to integer types
where one is of the unique plain 'char' type and the other is not
[-Wpointer-sign]
ELF(Word) chain = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket];
^~~~
parse_vdso.c:59:52: note: passing argument to parameter 'name' here
static unsigned long elf_hash(const unsigned char *name)
Fixes: 98eedc3a9dbf ("Document the vDSO and add a reference parser")
Signed-off-by: Edward Liaw <edliaw(a)google.com>
---
v2: update commit message with correct compiler warning
v3: fix checkpatch errors and indentation
---
tools/testing/selftests/vDSO/parse_vdso.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c
index 413f75620a35..9e29ff0657ea 100644
--- a/tools/testing/selftests/vDSO/parse_vdso.c
+++ b/tools/testing/selftests/vDSO/parse_vdso.c
@@ -203,8 +203,9 @@ void *vdso_sym(const char *version, const char *name)
if (!vdso_info.valid)
return 0;
- ver_hash = elf_hash(version);
- ELF(Word) chain = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket];
+ ver_hash = elf_hash((const unsigned char *)version);
+ ELF(Word) chain = vdso_info.bucket[
+ elf_hash((const unsigned char *)name) % vdso_info.nbucket];
for (; chain != STN_UNDEF; chain = vdso_info.chain[chain]) {
ELF(Sym) *sym = &vdso_info.symtab[chain];
--
2.45.0.rc0.197.gbae5840b3b-goog