From: david laight <david.laight@runbox.com>
To: Gui-Dong Han <hanguidong02@gmail.com>
Cc: linux@roeck-us.net, linux-hwmon@vger.kernel.org,
linux-kernel@vger.kernel.org, baijiaju1990@gmail.com,
stable@vger.kernel.org
Subject: Re: [PATCH] hwmon: (w83l786ng) Convert macros to functions to avoid TOCTOU
Date: Sat, 29 Nov 2025 10:17:36 +0000 [thread overview]
Message-ID: <20251129101736.000fac82@pumpkin> (raw)
In-Reply-To: <CALbr=LbYY-_-Uc_45fXDYzOMiYTJpwbNpuj41q2nHmdfangcBQ@mail.gmail.com>
On Sat, 29 Nov 2025 08:33:42 +0800
Gui-Dong Han <hanguidong02@gmail.com> wrote:
> On Sat, Nov 29, 2025 at 3:37 AM david laight <david.laight@runbox.com> wrote:
> >
> > On Fri, 28 Nov 2025 20:38:16 +0800
> > Gui-Dong Han <hanguidong02@gmail.com> wrote:
> >
> > > The macros FAN_FROM_REG and TEMP_FROM_REG evaluate their arguments
> > > multiple times. When used in lockless contexts involving shared driver
> > > data, this causes Time-of-Check to Time-of-Use (TOCTOU) race
> > > conditions.
> > >
> > > Convert the macros to static functions. This guarantees that arguments
> > > are evaluated only once (pass-by-value), preventing the race
> > > conditions.
> > >
> > > 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: 85f03bccd6e0 ("hwmon: Add support for Winbond W83L786NG/NR")
> > > 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/w83l786ng.c | 26 ++++++++++++++++++--------
> > > 1 file changed, 18 insertions(+), 8 deletions(-)
> > >
> > > diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c
> > > index 9b81bd406e05..1d9109ca1585 100644
> > > --- a/drivers/hwmon/w83l786ng.c
> > > +++ b/drivers/hwmon/w83l786ng.c
> > > @@ -76,15 +76,25 @@ FAN_TO_REG(long rpm, int div)
> > > return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
> > > }
> > >
> > > -#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \
> > > - ((val) == 255 ? 0 : \
> > > - 1350000 / ((val) * (div))))
> > > +static int fan_from_reg(int val, int div)
> > > +{
> > > + if (val == 0)
> > > + return -1;
> > > + if (val == 255)
> > > + return 0;
> > > + return 1350000 / (val * div);
> > > +}
> > >
> > > /* for temp */
> > > #define TEMP_TO_REG(val) (clamp_val(((val) < 0 ? (val) + 0x100 * 1000 \
> > > : (val)) / 1000, 0, 0xff))
> >
> > Can you change TEMP_TO_REG() as well.
> > And just use plain clamp() while you are at it.
> > Both these temperature conversion functions have to work with negative temperatures.
> > But the signed-ness gets passed through from the parameter - which may not be right.
> > IIRC some come from FIELD_GET() and will be 'unsigned long' unless cast somewhere.
> > The function parameter 'corrects' the type to a signed one.
> >
> > So you are fixing potential bugs as well.
>
> Hi David,
>
> Thanks for your feedback on TEMP_TO_REG and the detailed explanation
> regarding macro risks.
>
> Guenter has already applied this patch.
Patches are supposed to be posted for review and applied a few days later.
> Since the primary scope here
> was strictly addressing TOCTOU race conditions (and TEMP_TO_REG is not
> used in lockless contexts), it wasn't included.
>
> However, I appreciate your point regarding type safety. I will look
> into addressing that in a future separate patch.
It's not just type safety, and #define that evaluates an argument more
than one is just a bug waiting to happen.
We've been removing (or trying not to write) those since the 1980s.
You also just didn't read the code:
-#define TEMP_FROM_REG(val) (((val) & 0x80 ? \
- (val) - 0x100 : (val)) * 1000)
+
+static int temp_from_reg(int val)
+{
+ if (val & 0x80)
+ return (val - 0x100) * 1000;
+ return val * 1000;
+}
Both those only work if 'val' is 8 bits.
They are just ((s8)(val) * 1000) and generate a milli-centigrade
value from the 8-bit signed centigrade value the hardware provides.
TEMP_TO_REG() is the opposite, so is:
(u8)clamp((val) / 1000, -128, 127)
That is subtly different since it truncates negative values towards
zero rather than -infinity.
The more complicated:
(u8)(clamp(((val) + 128 * 1000)/1000, 0, 0xff) - 128)
would exactly match the original (and generate less code) but I suspect
it doesn't matter here.
David
>
> Best regards,
> Gui-Dong Han
>
next prev parent reply other threads:[~2025-11-29 10:17 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-28 12:38 [PATCH] hwmon: (w83l786ng) Convert macros to functions to avoid TOCTOU Gui-Dong Han
2025-11-28 16:30 ` Guenter Roeck
2025-11-28 19:37 ` david laight
2025-11-29 0:33 ` Gui-Dong Han
2025-11-29 10:17 ` david laight [this message]
2025-11-29 15:55 ` Guenter Roeck
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251129101736.000fac82@pumpkin \
--to=david.laight@runbox.com \
--cc=baijiaju1990@gmail.com \
--cc=hanguidong02@gmail.com \
--cc=linux-hwmon@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@roeck-us.net \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.