From 4617721c502b2ddaa4e324e86da4997edf738fa5 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 2 Sep 2026 09:55:01 -0400 Subject: ftrace: Synchronize the initialization of ftrace_ops There's some internal state that ftrace_ops needs to have set, but since it can be declared outside of the ftrace.c code, it calls ftrace_ops_init() on the ops in every global function. The issue is that if two tasks call it on the same ops at the same time it is possible to have the initialization of one corrupt the initialization of the other call. Create a ops_mutex to use to synchronize every initialization of the ftrace_ops. The mutex is taken within checking the ftrace_ops flag that states it was initializied but the flag is checked again after the mutex has been taken. Checking first outside the mutex allows it to shortcut having to take the mutex. But then the check needs to be done again after the mute is taken in case of races. Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260902095501.6b59af20@gandalf.local.home Fixes: f04f24fb7e48d ("ftrace, kprobes: Fix a deadlock on ftrace_regex_lock") Reported-by: sashiko-bot@kernel.org Close: https://lore.kernel.org/all/20260829025528.49A831F000E9@smtp.kernel.org/ Signed-off-by: Steven Rostedt --- drivers/hid/hid-generic.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 drivers/hid/hid-generic.c (limited to 'drivers/hid/hid-generic.c') diff --git a/drivers/hid/hid-generic.c b/drivers/hid/hid-generic.c new file mode 100644 index 000000000..c2de91674 --- /dev/null +++ b/drivers/hid/hid-generic.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * HID support for Linux + * + * Copyright (c) 1999 Andreas Gal + * Copyright (c) 2000-2005 Vojtech Pavlik + * Copyright (c) 2005 Michael Haboustak for Concept2, Inc + * Copyright (c) 2007-2008 Oliver Neukum + * Copyright (c) 2006-2012 Jiri Kosina + * Copyright (c) 2012 Henrik Rydberg + */ + +/* + */ + +#include +#include +#include +#include +#include + +#include + +static struct hid_driver hid_generic; + +static int __check_hid_generic(struct device_driver *drv, void *data) +{ + struct hid_driver *hdrv = to_hid_driver(drv); + struct hid_device *hdev = data; + + if (hdrv == &hid_generic) + return 0; + + return hid_match_device(hdev, hdrv) != NULL; +} + +static bool hid_generic_match(struct hid_device *hdev, + bool ignore_special_driver) +{ + if (ignore_special_driver) + return true; + + if (hdev->quirks & HID_QUIRK_IGNORE_SPECIAL_DRIVER) + return true; + + if (hdev->quirks & HID_QUIRK_HAVE_SPECIAL_DRIVER) + return false; + + /* + * If any other driver wants the device, leave the device to this other + * driver. + */ + if (bus_for_each_drv(&hid_bus_type, NULL, hdev, __check_hid_generic)) + return false; + + return true; +} + +static int hid_generic_probe(struct hid_device *hdev, + const struct hid_device_id *id) +{ + int ret; + + hdev->quirks |= HID_QUIRK_INPUT_PER_APP; + + ret = hid_parse(hdev); + if (ret) + return ret; + + return hid_hw_start(hdev, HID_CONNECT_DEFAULT); +} + +static int hid_generic_reset_resume(struct hid_device *hdev) +{ + if (hdev->claimed & HID_CLAIMED_INPUT) + hidinput_reset_resume(hdev); + + return 0; +} + +static const struct hid_device_id hid_table[] = { + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) }, + { } +}; +MODULE_DEVICE_TABLE(hid, hid_table); + +static struct hid_driver hid_generic = { + .name = "hid-generic", + .id_table = hid_table, + .match = hid_generic_match, + .probe = hid_generic_probe, + .reset_resume = hid_generic_reset_resume, +}; +module_hid_driver(hid_generic); + +MODULE_AUTHOR("Henrik Rydberg"); +MODULE_DESCRIPTION("HID generic driver"); +MODULE_LICENSE("GPL"); -- cgit v1.3.1