The function max6620_read checks shared data (tach and target) for zero before passing it to max6620_fan_tach_to_rpm, which uses it as a divisor. These accesses are currently lockless. If the data changes to zero between the check and the division, it causes a divide-by-zero error.
Explicitly acquire the update lock around these checks and calculations to ensure the data remains stable, preventing Time-of-Check to Time-of-Use (TOCTOU) race conditions.
This change also aligns the locking behavior with the hwmon_fan_alarm case, which already uses the update lock.
Link: https://lore.kernel.org/all/CALbr=LYJ_ehtp53HXEVkSpYoub+XYSTU8Rg=o1xxMJ8=5z8... Fixes: e8ac01e5db32 ("hwmon: Add Maxim MAX6620 hardware monitoring driver") Cc: stable@vger.kernel.org Signed-off-by: Gui-Dong Han hanguidong02@gmail.com --- Based on the discussion in the link, I will submit a series of patches to address TOCTOU issues in the hwmon subsystem by converting macros to functions or adjusting locking where appropriate. --- drivers/hwmon/max6620.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/hwmon/max6620.c b/drivers/hwmon/max6620.c index 13201fb755c9..0dce2f5cb61b 100644 --- a/drivers/hwmon/max6620.c +++ b/drivers/hwmon/max6620.c @@ -290,20 +290,24 @@ max6620_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, *val = max6620_fan_div_from_reg(data->fandyn[channel]); break; case hwmon_fan_input: + mutex_lock(&data->update_lock); if (data->tach[channel] == 0) { *val = 0; } else { div = max6620_fan_div_from_reg(data->fandyn[channel]); *val = max6620_fan_tach_to_rpm(div, data->tach[channel]); } + mutex_unlock(&data->update_lock); break; case hwmon_fan_target: + mutex_lock(&data->update_lock); if (data->target[channel] == 0) { *val = 0; } else { div = max6620_fan_div_from_reg(data->fandyn[channel]); *val = max6620_fan_tach_to_rpm(div, data->target[channel]); } + mutex_unlock(&data->update_lock); break; default: return -EOPNOTSUPP;