summaryrefslogtreecommitdiffstats
path: root/drivers/macintosh/mac_hid.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 /drivers/macintosh/mac_hid.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 'drivers/macintosh/mac_hid.c')
-rw-r--r--drivers/macintosh/mac_hid.c262
1 files changed, 262 insertions, 0 deletions
diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c
new file mode 100644
index 000000000..1fdf3855f
--- /dev/null
+++ b/drivers/macintosh/mac_hid.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * drivers/macintosh/mac_hid.c
+ *
+ * HID support stuff for Macintosh computers.
+ *
+ * Copyright (C) 2000 Franz Sirl.
+ *
+ * This file will soon be removed in favor of an uinput userspace tool.
+ */
+
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/sysctl.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+MODULE_DESCRIPTION("Mouse button 2+3 emulation");
+MODULE_LICENSE("GPL");
+
+static int mouse_emulate_buttons;
+static int mouse_button2_keycode = KEY_RIGHTCTRL; /* right control key */
+static int mouse_button3_keycode = KEY_RIGHTALT; /* right option key */
+
+static struct input_dev *mac_hid_emumouse_dev;
+
+static DEFINE_MUTEX(mac_hid_emumouse_mutex);
+
+static int mac_hid_create_emumouse(void)
+{
+ static struct lock_class_key mac_hid_emumouse_dev_event_class;
+ static struct lock_class_key mac_hid_emumouse_dev_mutex_class;
+ int err;
+
+ mac_hid_emumouse_dev = input_allocate_device();
+ if (!mac_hid_emumouse_dev)
+ return -ENOMEM;
+
+ lockdep_set_class(&mac_hid_emumouse_dev->event_lock,
+ &mac_hid_emumouse_dev_event_class);
+ lockdep_set_class(&mac_hid_emumouse_dev->mutex,
+ &mac_hid_emumouse_dev_mutex_class);
+
+ mac_hid_emumouse_dev->name = "Macintosh mouse button emulation";
+ mac_hid_emumouse_dev->id.bustype = BUS_ADB;
+ mac_hid_emumouse_dev->id.vendor = 0x0001;
+ mac_hid_emumouse_dev->id.product = 0x0001;
+ mac_hid_emumouse_dev->id.version = 0x0100;
+
+ mac_hid_emumouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+ mac_hid_emumouse_dev->keybit[BIT_WORD(BTN_MOUSE)] =
+ BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
+ mac_hid_emumouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+
+ err = input_register_device(mac_hid_emumouse_dev);
+ if (err) {
+ input_free_device(mac_hid_emumouse_dev);
+ mac_hid_emumouse_dev = NULL;
+ return err;
+ }
+
+ return 0;
+}
+
+static void mac_hid_destroy_emumouse(void)
+{
+ input_unregister_device(mac_hid_emumouse_dev);
+ mac_hid_emumouse_dev = NULL;
+}
+
+static bool mac_hid_emumouse_filter(struct input_handle *handle,
+ unsigned int type, unsigned int code,
+ int value)
+{
+ unsigned int btn;
+
+ if (type != EV_KEY)
+ return false;
+
+ if (code == mouse_button2_keycode)
+ btn = BTN_MIDDLE;
+ else if (code == mouse_button3_keycode)
+ btn = BTN_RIGHT;
+ else
+ return false;
+
+ input_report_key(mac_hid_emumouse_dev, btn, value);
+ input_sync(mac_hid_emumouse_dev);
+
+ return true;
+}
+
+static int mac_hid_emumouse_connect(struct input_handler *handler,
+ struct input_dev *dev,
+ const struct input_device_id *id)
+{
+ struct input_handle *handle;
+ int error;
+
+ /* Don't bind to ourselves */
+ if (dev == mac_hid_emumouse_dev)
+ return -ENODEV;
+
+ handle = kzalloc_obj(struct input_handle);
+ if (!handle)
+ return -ENOMEM;
+
+ handle->dev = dev;
+ handle->handler = handler;
+ handle->name = "mac-button-emul";
+
+ error = input_register_handle(handle);
+ if (error) {
+ printk(KERN_ERR
+ "mac_hid: Failed to register button emulation handle, "
+ "error %d\n", error);
+ goto err_free;
+ }
+
+ error = input_open_device(handle);
+ if (error) {
+ printk(KERN_ERR
+ "mac_hid: Failed to open input device, error %d\n",
+ error);
+ goto err_unregister;
+ }
+
+ return 0;
+
+ err_unregister:
+ input_unregister_handle(handle);
+ err_free:
+ kfree(handle);
+ return error;
+}
+
+static void mac_hid_emumouse_disconnect(struct input_handle *handle)
+{
+ input_close_device(handle);
+ input_unregister_handle(handle);
+ kfree(handle);
+}
+
+static const struct input_device_id mac_hid_emumouse_ids[] = {
+ {
+ .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
+ .evbit = { BIT_MASK(EV_KEY) },
+ },
+ { },
+};
+
+MODULE_DEVICE_TABLE(input, mac_hid_emumouse_ids);
+
+static struct input_handler mac_hid_emumouse_handler = {
+ .filter = mac_hid_emumouse_filter,
+ .connect = mac_hid_emumouse_connect,
+ .disconnect = mac_hid_emumouse_disconnect,
+ .name = "mac-button-emul",
+ .id_table = mac_hid_emumouse_ids,
+};
+
+static int mac_hid_start_emulation(void)
+{
+ int err;
+
+ err = mac_hid_create_emumouse();
+ if (err)
+ return err;
+
+ err = input_register_handler(&mac_hid_emumouse_handler);
+ if (err) {
+ mac_hid_destroy_emumouse();
+ return err;
+ }
+
+ return 0;
+}
+
+static void mac_hid_stop_emulation(void)
+{
+ input_unregister_handler(&mac_hid_emumouse_handler);
+ mac_hid_destroy_emumouse();
+}
+
+static int mac_hid_toggle_emumouse(const struct ctl_table *table, int write,
+ void *buffer, size_t *lenp, loff_t *ppos)
+{
+ int *valp = table->data;
+ int old_val;
+ int rc;
+
+ rc = mutex_lock_killable(&mac_hid_emumouse_mutex);
+ if (rc)
+ return rc;
+
+ old_val = *valp;
+ rc = proc_dointvec(table, write, buffer, lenp, ppos);
+
+ if (rc == 0 && write && *valp != old_val) {
+ if (*valp == 1)
+ rc = mac_hid_start_emulation();
+ else if (*valp == 0)
+ mac_hid_stop_emulation();
+ else
+ rc = -EINVAL;
+ }
+
+ /* Restore the old value in case of error */
+ if (rc)
+ *valp = old_val;
+
+ mutex_unlock(&mac_hid_emumouse_mutex);
+
+ return rc;
+}
+
+/* file(s) in /proc/sys/dev/mac_hid */
+static const struct ctl_table mac_hid_files[] = {
+ {
+ .procname = "mouse_button_emulation",
+ .data = &mouse_emulate_buttons,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = mac_hid_toggle_emumouse,
+ },
+ {
+ .procname = "mouse_button2_keycode",
+ .data = &mouse_button2_keycode,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+ {
+ .procname = "mouse_button3_keycode",
+ .data = &mouse_button3_keycode,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+};
+
+static struct ctl_table_header *mac_hid_sysctl_header;
+
+static int __init mac_hid_init(void)
+{
+ mac_hid_sysctl_header = register_sysctl("dev/mac_hid", mac_hid_files);
+ if (!mac_hid_sysctl_header)
+ return -ENOMEM;
+
+ return 0;
+}
+module_init(mac_hid_init);
+
+static void __exit mac_hid_exit(void)
+{
+ unregister_sysctl_table(mac_hid_sysctl_header);
+
+ if (mouse_emulate_buttons)
+ mac_hid_stop_emulation();
+}
+module_exit(mac_hid_exit);