lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251118-wip-sync-udev-hid-bpf-v1-4-0f8105c54835@kernel.org>
Date: Tue, 18 Nov 2025 18:16:25 +0100
From: Benjamin Tissoires <bentiss@...nel.org>
To: Jiri Kosina <jikos@...nel.org>
Cc: linux-kernel@...r.kernel.org, linux-input@...r.kernel.org, 
 Benjamin Tissoires <bentiss@...nel.org>, 
 Curran Muhlberger <curran@...cornell.edu>
Subject: [PATCH 04/10] HID: bpf: Add fixup for Logitech SpaceNavigator
 variants

The 3Dconnexion SpaceNavigator HID report descriptor declares its axis
data to be "relative" when it is actually "absolute".  This quirk was
addressed in the kernel in 2.6.33, but some SpaceNavigator variants have
a slightly different report descriptor whose axis input items are at
different offsets than those assumed by the kernel fixup.

Add a BPF fixup to handle both sets of offsets for known SpaceNavigator
variants if the descriptor has not already been fixed by the kernel.

Signed-off-by: Curran Muhlberger <curran@...cornell.edu>
Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/181
Signed-off-by: Benjamin Tissoires <bentiss@...nel.org>
---
 .../hid/bpf/progs/Logitech__SpaceNavigator.bpf.c   | 86 ++++++++++++++++++++++
 1 file changed, 86 insertions(+)

diff --git a/drivers/hid/bpf/progs/Logitech__SpaceNavigator.bpf.c b/drivers/hid/bpf/progs/Logitech__SpaceNavigator.bpf.c
new file mode 100644
index 0000000000000000000000000000000000000000..b17719d6d9c71e7b538d75c7a7197b4e1fead213
--- /dev/null
+++ b/drivers/hid/bpf/progs/Logitech__SpaceNavigator.bpf.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2025 Curran Muhlberger
+ */
+
+#include "vmlinux.h"
+#include "hid_bpf.h"
+#include "hid_bpf_helpers.h"
+#include <bpf/bpf_tracing.h>
+
+#define VID_LOGITECH 0x046D
+#define PID_SPACENAVIGATOR 0xC626
+
+HID_BPF_CONFIG(
+	HID_DEVICE(BUS_USB, HID_GROUP_ANY, VID_LOGITECH, PID_SPACENAVIGATOR)
+);
+
+/*
+ * The 3Dconnexion SpaceNavigator 3D Mouse is a multi-axis controller with 6
+ * axes (grouped as X,Y,Z and Rx,Ry,Rz).  Axis data is absolute, but the report
+ * descriptor erroneously declares it to be relative.  We fix the report
+ * descriptor to mark both axis collections as absolute.
+ *
+ * The kernel attempted to fix this in commit 24985cf68612 (HID: support
+ * Logitech/3DConnexion SpaceTraveler and SpaceNavigator), but the descriptor
+ * data offsets are incorrect for at least some SpaceNavigator units.
+ */
+
+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 */);
+
+	if (!data)
+		return 0; /* EPERM check */
+
+	/* Offset of Input item in X,Y,Z and Rx,Ry,Rz collections for all known
+	 * firmware variants.
+	 * - 2009 model: X,Y,Z @ 32-33, Rx,Ry,Rz @ 49-50 (fixup originally
+	 *   applied in kernel)
+	 * - 2016 model (size==228): X,Y,Z @ 36-37, Rx,Ry,Rz @ 53-54
+	 *
+	 * The descriptor size of the 2009 model is not known, and there is evidence
+	 * for at least two other variants (with sizes 202 & 217) besides the 2016
+	 * model, so we try all known offsets regardless of descriptor size.
+	 */
+	const u8 offsets[] = {32, 36, 49, 53};
+
+	for (size_t idx = 0; idx < ARRAY_SIZE(offsets); idx++) {
+		u8 offset = offsets[idx];
+
+		/* if Input (Data,Var,Rel) , make it Input (Data,Var,Abs) */
+		if (data[offset] == 0x81 && data[offset + 1] == 0x06)
+			data[offset + 1] = 0x02;
+	}
+
+	return 0;
+}
+
+HID_BPF_OPS(logitech_spacenavigator) = {
+	.hid_rdesc_fixup = (void *)hid_fix_rdesc,
+};
+
+SEC("syscall")
+int probe(struct hid_bpf_probe_args *ctx)
+{
+	/* Ensure report descriptor size matches one of the known variants. */
+	if (ctx->rdesc_size != 202 &&
+	    ctx->rdesc_size != 217 &&
+	    ctx->rdesc_size != 228) {
+		ctx->retval = -EINVAL;
+		return 0;
+	}
+
+	/* Check whether the kernel has already applied the fix. */
+	if ((ctx->rdesc[32] == 0x81 && ctx->rdesc[33] == 0x02 &&
+	     ctx->rdesc[49] == 0x81 && ctx->rdesc[50] == 0x02) ||
+	    (ctx->rdesc[36] == 0x81 && ctx->rdesc[37] == 0x02 &&
+	     ctx->rdesc[53] == 0x81 && ctx->rdesc[54] == 0x02))
+		ctx->retval = -EINVAL;
+	else
+		ctx->retval = 0;
+
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";

-- 
2.51.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ