]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selftests/hid: Cover hid_bpf_get_data() size overflow
authorYiyang Chen <chenyy23@mails.tsinghua.edu.cn>
Tue, 23 Jun 2026 06:23:15 +0000 (06:23 +0000)
committerBenjamin Tissoires <bentiss@kernel.org>
Wed, 1 Jul 2026 07:55:36 +0000 (09:55 +0200)
Add a HID-BPF regression check for hid_bpf_get_data() requests whose
size would overflow when added to the offset.

The new rdesc fixup callback asks for offset 2 and size ~0ULL, then
records whether the helper returns NULL. A vulnerable kernel returns a
non-NULL pointer because the runtime check wraps the addition. A fixed
kernel rejects the request. The callback records the helper result
without dereferencing any returned pointer.

The callback reports the helper result through BSS and returns 0
intentionally. hid_rdesc_fixup return values are consumed as report
descriptor fixup results, so a positive test-result value would be
interpreted as a replacement report descriptor size.

Also add KHDR_INCLUDES to the HID selftest build so hid_bpf.c sees the
current kernel UAPI HID definitions on systems whose installed headers do
not provide enum hid_report_type.

Fixes: 658ee5a64fcf ("HID: bpf: allocate data memory for device_event BPF programs")
Signed-off-by: Yiyang Chen <chenyy23@mails.tsinghua.edu.cn>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
tools/testing/selftests/hid/Makefile
tools/testing/selftests/hid/hid_bpf.c
tools/testing/selftests/hid/progs/hid.c

index 96071b4800e82a8f434c0ad1f91d88e0cfc77081..2f423de831473a4a3370a1a49a61f86290a97758 100644 (file)
@@ -24,7 +24,7 @@ CXX ?= $(CROSS_COMPILE)g++
 
 HOSTPKG_CONFIG := pkg-config
 
-CFLAGS += -g -O0 -rdynamic -Wall -Werror -I$(OUTPUT)
+CFLAGS += -g -O0 -rdynamic -Wall -Werror -I$(OUTPUT) $(KHDR_INCLUDES)
 CFLAGS += -I$(OUTPUT)/tools/include
 
 LDLIBS += -lelf -lz -lrt -lpthread
index 269256e1decd843d2f35c7524a413ac26548e2e0..b851339308c214f71e3ed26c017bb90563d2f2e1 100644 (file)
@@ -898,6 +898,17 @@ TEST_F(hid_bpf, test_rdesc_fixup)
        ASSERT_EQ(rpt_desc.value[4], 0x42);
 }
 
+TEST_F(hid_bpf, test_rdesc_fixup_get_data_overflow)
+{
+       const struct test_program progs[] = {
+               { .name = "hid_rdesc_fixup_get_data_overflow" },
+       };
+
+       LOAD_PROGRAMS(progs);
+
+       ASSERT_EQ(self->skel->bss->get_data_overflow_check, 1);
+}
+
 static int libbpf_print_fn(enum libbpf_print_level level,
                           const char *format, va_list args)
 {
index 5ecc845ef79216d42e141e42167289109ea79267..b21fbb13c926f82585fb7ff4f6dfc93025c1fe9e 100644 (file)
@@ -13,6 +13,7 @@ struct attach_prog_args {
 
 __u64 callback_check = 52;
 __u64 callback2_check = 52;
+__u64 get_data_overflow_check;
 
 SEC("?struct_ops/hid_device_event")
 int BPF_PROG(hid_first_event, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
@@ -240,6 +241,20 @@ struct hid_bpf_ops rdesc_fixup = {
        .hid_rdesc_fixup = (void *)hid_rdesc_fixup,
 };
 
+SEC("?struct_ops.s/hid_rdesc_fixup")
+int BPF_PROG(hid_rdesc_fixup_get_data_overflow, struct hid_bpf_ctx *hid_ctx)
+{
+       if (!hid_bpf_get_data(hid_ctx, 2 /* offset */, ~0ULL /* size */))
+               get_data_overflow_check = 1;
+
+       return 0;
+}
+
+SEC(".struct_ops.link")
+struct hid_bpf_ops rdesc_fixup_get_data_overflow = {
+       .hid_rdesc_fixup = (void *)hid_rdesc_fixup_get_data_overflow,
+};
+
 SEC("?struct_ops/hid_device_event")
 int BPF_PROG(hid_test_insert1, struct hid_bpf_ctx *hid_ctx, enum hid_report_type type)
 {