From nobody Tue Jun 16 04:59:21 2026 Received: from mail-dl1-f48.google.com (mail-dl1-f48.google.com [74.125.82.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7C6CB34C826 for ; Thu, 16 Apr 2026 13:57:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776347846; cv=none; b=qxBZo25jaA4WqQF2g1KbtLDRXTY+Cqcap3Cy6s8a1M09nW/WOBtN1Uda816/+xR0u/XvfJUaRrdsp4Fy2IujVHnxFFnlG+qOKXxjrMUVyH4m3U24J8LzlIwetWo3exIBe58u37JUDBaJplw63qPeU6PGcBQpF0svRX6dQbzoHWE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776347846; c=relaxed/simple; bh=qsJOp3oaXr2w4iGEmJiErCNfUdrDVwPgYREwOIeomeY=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=G1n6NcRVauhIeB5XfU5NRNx+fEc8vttWmIhFn3cBCksHLAhaYN8X9TZCra56foeCxu7eTJk+BLUFkPkpn/8k3wt4rC08cXr+5PfmRswUgf83fxVhEaRKhWn0QGi3tSjNO7BWwaVh1T3AJFCGiYkGhzNKfqA47jd+7X3eBcs8ktQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=glR7kbZR; arc=none smtp.client-ip=74.125.82.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="glR7kbZR" Received: by mail-dl1-f48.google.com with SMTP id a92af1059eb24-12c565476d7so3200247c88.1 for ; Thu, 16 Apr 2026 06:57:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776347844; x=1776952644; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=9AwViEObe+yE4RqzPsI6fiKZ5hGYwUKWmhw1eqkO5OM=; b=glR7kbZRefhC7RLVCiIOM9PwIJ4/3xO7FEiOJPvCZzSrXAeS1MYEGsiKtPAWYYGl7s gH2x7U7hLy9V7o8+lNQHcNXjYXbIwIIQ8uZHNc80X2BEHaH+ui3m5tX974mQZ2MIE8ga Tu2TPoHI0ui+5UrDTe81X66MlCpfGmrT14aUTF9mXz7EqlFo8VrslDwH//p8mqerJx9c dGJ5ErTDph8H6Y1Cra5yzVVINVhd0dnYOtVQdFrRbYE02qNIEHY8SuoIBytR4tg9wdF5 JAeB53NOWyb63P8c1iKiItggPpoeZVd6OHiKmTgg1PczewE1MVu9zcNfwTt5W4HyNGF6 6L/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776347844; x=1776952644; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=9AwViEObe+yE4RqzPsI6fiKZ5hGYwUKWmhw1eqkO5OM=; b=X0SUfwpoXiNL4EdSMCTZiQH0T1e7+EwK9bmO4C4qmw11yBPURzeSFh59fwYHtZM2Fb +42mWjdQQhcPOTtugFyKK9ZXxuzVbsMu8C+x9SkjcdcvJtUnDUzlEw5oD5jM8X+xe3w+ l7/HaCXDnvFuoJyXJLi2SNFYkcGXbgkRbI9qvD/TvqHWB37z/hIuKkbFVHCJd7EDoQ9i FuvaVcm4s0hW7zJigutQky4zeh3QhjYC9IfndZFdWr87mYE04QJkNiKbXmTkMMyONxXK vUbpmj9pNI+pAwI0+gmVSeDP1xdcsKEJziuQ3KMwCHc+sJxGlbrq0Ro62kNfzBYRsfFT X9OQ== X-Forwarded-Encrypted: i=1; AFNElJ99JFZqFggxe7IXTnQ+0zsvREtgHpf6DUNIk3iJuQpgE3kPiDrJ3f2O37uCFZOV9wnLDRU7mIVJ1HUX0rU=@vger.kernel.org X-Gm-Message-State: AOJu0YykETyZVsJqaJWkkRtnlHl982pOllP9oNnhTAQsxN49VUGpxl1H y9tjwpyiv7VB6jZV4JRUJSTvyl3eGSw1KgOEFdSLPIILPK1HeUs1+yAQ X-Gm-Gg: AeBDiesPL7dapefU8c04AVoR9UTpbGYeF6WeTvkb7EHasX7/GrsJd0O6O2ea08wVIq9 9Aaa6nOGnaJ8RBrOOum5mRmmlC3ICEsGRCoHIMcUu72I8uWJXfnoyNyEI1v3z3/Zabx2rlxIjA3 yZUmxND13O5Q/bHJcSJwU5abSU3f7Q8qmQdQ8xZ2Fy6DqGAv9x1vr8U/a0KIPUA0TUdQH/aBAXy 8YgnwKVky8CpMrjo2PpvasbJyJlEas8q1nSswKxRYY0gvjOJr1j+K4GHyhCgL+WM7Yp+APYR5qs AI7kpUWavB+2nCLJ03UqrIeXXAPfHJhDIAIfruwRvVZDAoGi5cn+8uPsXtNhf9ciCSdxfNdOXNJ 5c/EJJ7sKYCzoCmxyRU09D5d/yA4rJKpYW6oX2Nj7/G65VcN4bLvF+D37vieJurknC9fZU5DJl7 kMAz3OgSpjz7TNSnZ7PBuL+uSndWdFUMGkwBDqW+3DBDG+4//8gwRat3Lp2+F5sOrobK3V+LSF1 J/Suc5pUW9uuREZhUnQkV9L4k3uaZLjGm6LnRIiHsAFuC71BwhYducN7labwwUW5XYB87cuYHev tYrdh8SxZNoYs3qU7CuP/Mo= X-Received: by 2002:a05:7300:7c0c:b0:2c5:60d0:701e with SMTP id 5a478bee46e88-2d586ea78f5mr15495567eec.3.1776347844222; Thu, 16 Apr 2026 06:57:24 -0700 (PDT) Received: from 2045L.localdomain (49.sub-75-226-46.myvzw.com. [75.226.46.49]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2de8f6615d5sm9150638eec.24.2026.04.16.06.57.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Apr 2026 06:57:23 -0700 (PDT) From: Gui-Dong Han To: Guenter Roeck Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org, baijiaju1990@gmail.com, Gui-Dong Han Subject: [PATCH v2] hwmon: (lm63) Add locking to avoid TOCTOU Date: Thu, 16 Apr 2026 21:57:03 +0800 Message-ID: <20260416135703.53262-1-hanguidong02@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The functions show_fan(), show_pwm1(), show_temp11(), temp2_crit_hyst_show(), and show_lut_temp_hyst() access shared cached data without holding the update lock. This can cause TOCTOU races if the cached values change between the checks and the later calculations. Those cached values are updated in lm63_update_device(). In the general case, the affected functions combine multiple cached values without locking and can therefore observe a mixed old/new snapshot. In addition, show_fan() reads data->fan[nr] locklessly while lm63_update_device() updates data->fan[0] in two steps, which can expose an intermediate torn value and potentially trigger a divide-by-zero error. This means that converting the macro to a function is not sufficient to fix show_fan(). Hold the update lock across the whole read and calculation sequence so that the values remain stable. Check the other functions in the driver as well. Keep them unchanged because they either do not access shared cached values multiple times or already do so under lock. Link: https://lore.kernel.org/linux-hwmon/CALbr=3DLYJ_ehtp53HXEVkSpYoub+XYS= TU8Rg=3Do1xxMJ8=3D5z8B-g@mail.gmail.com/ Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Fixes: e872c91e726e ("hwmon: (lm63) Add support for unsigned upper temperat= ure limits") Fixes: d216f6809eb6 ("hwmon: (lm63) Expose automatic fan speed control look= up table") Signed-off-by: Gui-Dong Han --- v2: - Sashiko-bot pointed out that show_fan(), temp2_crit_hyst_show(), and show_lut_temp_hyst() also need locking. While learning the hwmon driver code, I found a few more potential TOCTOU problems in drivers still using the older non-_with_info() APIs. Fix them. --- drivers/hwmon/lm63.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 035176a98ce9..b8b1de5fa90f 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c @@ -333,7 +333,13 @@ static ssize_t show_fan(struct device *dev, struct dev= ice_attribute *devattr, { struct sensor_device_attribute *attr =3D to_sensor_dev_attr(devattr); struct lm63_data *data =3D lm63_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index])); + int fan; + + mutex_lock(&data->update_lock); + fan =3D FAN_FROM_REG(data->fan[attr->index]); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", fan); } =20 static ssize_t set_fan(struct device *dev, struct device_attribute *dummy, @@ -366,12 +372,14 @@ static ssize_t show_pwm1(struct device *dev, struct d= evice_attribute *devattr, int nr =3D attr->index; int pwm; =20 + mutex_lock(&data->update_lock); if (data->pwm_highres) pwm =3D data->pwm1[nr]; else pwm =3D data->pwm1[nr] >=3D 2 * data->pwm1_freq ? 255 : (data->pwm1[nr] * 255 + data->pwm1_freq) / (2 * data->pwm1_freq); + mutex_unlock(&data->update_lock); =20 return sprintf(buf, "%d\n", pwm); } @@ -529,6 +537,7 @@ static ssize_t show_temp11(struct device *dev, struct d= evice_attribute *devattr, int nr =3D attr->index; int temp; =20 + mutex_lock(&data->update_lock); if (!nr) { /* * Use unsigned temperature unless its value is zero. @@ -544,7 +553,10 @@ static ssize_t show_temp11(struct device *dev, struct = device_attribute *devattr, else temp =3D TEMP11_FROM_REG(data->temp11[nr]); } - return sprintf(buf, "%d\n", temp + data->temp2_offset); + temp +=3D data->temp2_offset; + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", temp); } =20 static ssize_t set_temp11(struct device *dev, struct device_attribute *dev= attr, @@ -592,9 +604,14 @@ static ssize_t temp2_crit_hyst_show(struct device *dev, struct device_attribute *dummy, char *buf) { struct lm63_data *data =3D lm63_update_device(dev); - return sprintf(buf, "%d\n", temp8_from_reg(data, 2) - + data->temp2_offset - - TEMP8_FROM_REG(data->temp2_crit_hyst)); + int temp; + + mutex_lock(&data->update_lock); + temp =3D temp8_from_reg(data, 2) + data->temp2_offset + - TEMP8_FROM_REG(data->temp2_crit_hyst); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", temp); } =20 static ssize_t show_lut_temp_hyst(struct device *dev, @@ -602,10 +619,14 @@ static ssize_t show_lut_temp_hyst(struct device *dev, { struct sensor_device_attribute *attr =3D to_sensor_dev_attr(devattr); struct lm63_data *data =3D lm63_update_device(dev); + int temp; =20 - return sprintf(buf, "%d\n", lut_temp_from_reg(data, attr->index) - + data->temp2_offset - - TEMP8_FROM_REG(data->lut_temp_hyst)); + mutex_lock(&data->update_lock); + temp =3D lut_temp_from_reg(data, attr->index) + data->temp2_offset + - TEMP8_FROM_REG(data->lut_temp_hyst); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", temp); } =20 /* --=20 2.43.0