Skip to content

Commit 670d7ef

Browse files
2045geminigroeck
authored andcommitted
hwmon: (w83791d) Convert macros to functions to avoid TOCTOU
The macro FAN_FROM_REG evaluates its arguments multiple times. When used in lockless contexts involving shared driver data, this leads to Time-of-Check to Time-of-Use (TOCTOU) race conditions, potentially causing divide-by-zero errors. Convert the macro to a static function. This guarantees that arguments are evaluated only once (pass-by-value), preventing the race conditions. Additionally, in store_fan_div, move the calculation of the minimum limit inside the update lock. This ensures that the read-modify-write sequence operates on consistent data. Adhere to the principle of minimal changes by only converting macros that evaluate arguments multiple times and are used in lockless contexts. Link: https://lore.kernel.org/all/CALbr=LYJ_ehtp53HXEVkSpYoub+XYSTU8Rg=o1xxMJ8=5z8B-g@mail.gmail.com/ Fixes: 9873964 ("[PATCH] HWMON: w83791d: New hardware monitoring driver for the Winbond W83791D") Cc: stable@vger.kernel.org Signed-off-by: Gui-Dong Han <hanguidong02@gmail.com> Link: https://lore.kernel.org/r/20251202180105.12842-1-hanguidong02@gmail.com Signed-off-by: Guenter Roeck <linux@roeck-us.net>
1 parent 67a454e commit 670d7ef

1 file changed

Lines changed: 11 additions & 6 deletions

File tree

drivers/hwmon/w83791d.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,14 @@ static u8 fan_to_reg(long rpm, int div)
218218
return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
219219
}
220220

221-
#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \
222-
((val) == 255 ? 0 : \
223-
1350000 / ((val) * (div))))
221+
static int fan_from_reg(int val, int div)
222+
{
223+
if (val == 0)
224+
return -1;
225+
if (val == 255)
226+
return 0;
227+
return 1350000 / (val * div);
228+
}
224229

225230
/* for temp1 which is 8-bit resolution, LSB = 1 degree Celsius */
226231
#define TEMP1_FROM_REG(val) ((val) * 1000)
@@ -521,7 +526,7 @@ static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
521526
struct w83791d_data *data = w83791d_update_device(dev); \
522527
int nr = sensor_attr->index; \
523528
return sprintf(buf, "%d\n", \
524-
FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
529+
fan_from_reg(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
525530
}
526531

527532
show_fan_reg(fan);
@@ -585,10 +590,10 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr,
585590
if (err)
586591
return err;
587592

593+
mutex_lock(&data->update_lock);
588594
/* Save fan_min */
589-
min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
595+
min = fan_from_reg(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
590596

591-
mutex_lock(&data->update_lock);
592597
data->fan_div[nr] = div_to_reg(nr, val);
593598

594599
switch (nr) {

0 commit comments

Comments
 (0)