summaryrefslogtreecommitdiffstats
path: root/samples/hid/hid_mouse.bpf.c
diff options
context:
space:
mode:
authorMuhammad Bilal <meatuni001@gmail.com>2026-07-28 17:54:55 +0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-09-01 12:15:16 +0200
commitff917923f4fb9c83717ba135ee47d7e4c1567bb7 (patch)
treec38fd8fcf58e1937b17fdbc6518b6f8b797fc15a /samples/hid/hid_mouse.bpf.c
downloadlinux-stable-ff917923f4fb9c83717ba135ee47d7e4c1567bb7.tar.gz
linux-stable-ff917923f4fb9c83717ba135ee47d7e4c1567bb7.zip
staging: rtl8723bs: fix OOB read in rtw_action_frame_parse()grafted
rtw_action_frame_parse() takes a frame_len parameter but never actually checks it before indexing into the frame body: const u8 *frame_body = frame + sizeof(struct ieee80211_hdr_3addr); ... c = frame_body[0]; ... a = frame_body[1]; frame_body already points 24 bytes (sizeof(struct ieee80211_hdr_3addr)) into frame, so reading frame_body[0] and frame_body[1] requires frame_len >= 26. A management action frame shorter than that (e.g. exactly 24 bytes, the minimum a malicious peer can send) causes a 1-2 byte out-of-bounds read. This is reachable from rtw_cfg80211_monitor_if_xmit_entry() and cfg80211_rtw_mgmt_tx() in ioctl_cfg80211.c, both of which pass attacker/user-influenced frame buffers and lengths straight through. Add the missing length check before frame_body is dereferenced. Fixes: 554c0a3abf216 ("staging: Add rtl8723bs sdio wifi driver") Cc: stable@vger.kernel.org Signed-off-by: Muhammad Bilal <meatuni001@gmail.com> Link: https://patch.msgid.link/20260728125456.32359-3-meatuni001@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'samples/hid/hid_mouse.bpf.c')
-rw-r--r--samples/hid/hid_mouse.bpf.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/samples/hid/hid_mouse.bpf.c b/samples/hid/hid_mouse.bpf.c
new file mode 100644
index 000000000..f7f722dcf
--- /dev/null
+++ b/samples/hid/hid_mouse.bpf.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include "hid_bpf_helpers.h"
+
+static int hid_y_event(struct hid_bpf_ctx *hctx)
+{
+ s16 y;
+ __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
+
+ if (!data)
+ return 0; /* EPERM check */
+
+ bpf_printk("event: size: %d", hctx->size);
+ bpf_printk("incoming event: %02x %02x %02x",
+ data[0],
+ data[1],
+ data[2]);
+ bpf_printk(" %02x %02x %02x",
+ data[3],
+ data[4],
+ data[5]);
+ bpf_printk(" %02x %02x %02x",
+ data[6],
+ data[7],
+ data[8]);
+
+ y = data[3] | (data[4] << 8);
+
+ y = -y;
+
+ data[3] = y & 0xFF;
+ data[4] = (y >> 8) & 0xFF;
+
+ bpf_printk("modified event: %02x %02x %02x",
+ data[0],
+ data[1],
+ data[2]);
+ bpf_printk(" %02x %02x %02x",
+ data[3],
+ data[4],
+ data[5]);
+ bpf_printk(" %02x %02x %02x",
+ data[6],
+ data[7],
+ data[8]);
+
+ return 0;
+}
+
+static int hid_x_event(struct hid_bpf_ctx *hctx)
+{
+ s16 x;
+ __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
+
+ if (!data)
+ return 0; /* EPERM check */
+
+ x = data[1] | (data[2] << 8);
+
+ x = -x;
+
+ data[1] = x & 0xFF;
+ data[2] = (x >> 8) & 0xFF;
+ return 0;
+}
+
+SEC("struct_ops/hid_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/hid_rdesc_fixup")
+int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
+{
+ __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
+
+ if (!data)
+ return 0; /* EPERM check */
+
+ bpf_printk("rdesc: %02x %02x %02x",
+ data[0],
+ data[1],
+ data[2]);
+ bpf_printk(" %02x %02x %02x",
+ data[3],
+ data[4],
+ data[5]);
+ bpf_printk(" %02x %02x %02x ...",
+ data[6],
+ data[7],
+ data[8]);
+
+ /*
+ * The original report descriptor contains:
+ *
+ * 0x05, 0x01, // Usage Page (Generic Desktop) 30
+ * 0x16, 0x01, 0x80, // Logical Minimum (-32767) 32
+ * 0x26, 0xff, 0x7f, // Logical Maximum (32767) 35
+ * 0x09, 0x30, // Usage (X) 38
+ * 0x09, 0x31, // Usage (Y) 40
+ *
+ * So byte 39 contains Usage X and byte 41 Usage Y.
+ *
+ * We simply swap the axes here.
+ */
+ data[39] = 0x31;
+ data[41] = 0x30;
+
+ return 0;
+}
+
+SEC(".struct_ops.link")
+struct hid_bpf_ops mouse_invert = {
+ .hid_rdesc_fixup = (void *)hid_rdesc_fixup,
+ .hid_device_event = (void *)hid_event,
+};
+
+char _license[] SEC("license") = "GPL";