From: Ali Ahmet Memis Date: Thu, 6 Aug 2026 14:21:39 +0000 (+0000) Subject: hwmon: (corsair-psu) serialize debugfs access against hwmon X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=2da6050809d437a805e7a3aa22398a15073b0234;p=thirdparty%2Fkernel%2Flinux.git hwmon: (corsair-psu) serialize debugfs access against hwmon corsairpsu_request() sends a rail select command and then the actual read as two separate transfers, both going through the single shared cmd_buffer and wait_completion in corsairpsu_usb_cmd(). The hwmon core serializes its own callers, but the debugfs files call corsairpsu_get_value() directly and never take that lock, so a debugfs read can land between another reader's rail select and its value read. The result is a value from the wrong rail reported as the right one, because corsairpsu_usb_cmd() only checks the command echo and both transfers echo the command it expects. It can also make a caller consume the reply meant for the other one, since raw_event() writes into the shared buffer and completes whoever happens to be waiting. Locking was dropped in commit 4207069edbf0 ("hwmon: (corsair-psu) Rely on subsystem locking") on the grounds that the subsystem serializes for us, which holds for sysfs but not for these files. Take the same lock in the debugfs paths that issue commands, using the guard added in commit d1e720c7328e ("hwmon: Support guard() and scoped_guard for subsystem locks"). The lock cannot go into corsairpsu_request() itself: the hwmon core already holds it across ->read, so every sysfs read would deadlock. vendor_show() and product_show() only print strings cached during probe and issue no command, and corsairpsu_get_criticals() and corsairpsu_check_cmd_support() run before either interface is registered, so none of them need it. Fixes: 4207069edbf0 ("hwmon: (corsair-psu) Rely on subsystem locking") Signed-off-by: Ali Ahmet Memis Tested-by: Wilken Gottwalt Link: https://lore.kernel.org/r/20260806142139.168611-1-ali@iusegentoo.com Signed-off-by: Guenter Roeck --- diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c index 3c01ae3fc4af..ebcaddf337d8 100644 --- a/drivers/hwmon/corsair-psu.c +++ b/drivers/hwmon/corsair-psu.c @@ -664,6 +664,8 @@ static void print_uptime(struct seq_file *seqf, u8 cmd) long val; int ret; + guard(hwmon_lock)(priv->hwmon_dev); + ret = corsairpsu_get_value(priv, cmd, 0, &val); if (ret < 0) { seq_puts(seqf, "N/A\n"); @@ -723,6 +725,8 @@ static int ocpmode_show(struct seq_file *seqf, void *unused) long val; int ret; + guard(hwmon_lock)(priv->hwmon_dev); + /* * The rail mode is switchable on the fly. The RAW interface can be used for this. But it * will not be included here, because I consider it somewhat dangerous for the health of the