]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
hwmon: (corsair-psu) serialize debugfs access against hwmon
authorAli Ahmet Memis <ali@iusegentoo.com>
Thu, 6 Aug 2026 14:21:39 +0000 (14:21 +0000)
committerGuenter Roeck <linux@roeck-us.net>
Fri, 7 Aug 2026 05:37:45 +0000 (22:37 -0700)
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 <ali@iusegentoo.com>
Tested-by: Wilken Gottwalt <wilken.gottwalt@posteo.net>
Link: https://lore.kernel.org/r/20260806142139.168611-1-ali@iusegentoo.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/corsair-psu.c

index 3c01ae3fc4af224f2be14862653ee3eff3ffc6de..ebcaddf337d807bcf26cb38759fe99c10fbbd65b 100644 (file)
@@ -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