mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Thomas Weißschuh" <linux@weissschuh.net>
To: Guenter Roeck <linux@roeck-us.net>
Cc: Benson Leung <bleung@chromium.org>,
	 Guenter Roeck <groeck@chromium.org>,
	chrome-platform@lists.linux.dev, linux-hwmon@vger.kernel.org,
	 linux-kernel@vger.kernel.org
Subject: Re: [PATCH 2/2] hwmon: (cros_ec) Handle temperature conversion overflows
Date: Tue, 7 Jul 2026 18:52:22 +0200	[thread overview]
Message-ID: <2b1c29c8-bf87-4113-ba1e-63e1b1d1ff51@t-8ch.de> (raw)
In-Reply-To: <7b5145a6-7054-40c7-af49-1f2415d1b83f@roeck-us.net>

On 2026-06-30 16:06:04-0700, Guenter Roeck wrote:
> On Tue, Jun 30, 2026 at 10:57:52PM +0200, Thomas Weißschuh wrote:
> > The calculations converting between the different temperature units can
> > overflow, resulting in incorrect data.
> > 
> > Detect these overflows and report them.
> > 
> 
> I did not see how this can happen in practice, so I asked an AI agent.
> Its response is below.
>
> Given that, I am not going to apply this patch. I am all for checking
> against overflows, but only if they are real.

They can happen on 32-bit architectures. 
So my idea was to have a single shared algorithm for which the compiler
will nicely optimize away the impossible cases.

(More below)

> ---
> Yes, an overflow is possible, but only on 32-bit architectures.
>   
>   Here is the breakdown of why this happens and its limitations:
>   
>   ### 1.  cros_ec_hwmon_read_temp_threshold 
>   
>   The function  cros_ec_hwmon_read_temp_threshold  populates the  threshold  variable using  resp.temp_host[threshold] , which is an array of  uint32_t .
>   
>   In  cros_ec_hwmon_read , this  u32  threshold is passed to the conversion function which takes a  long t :
>   
>     static bool cros_ec_hwmon_kelvin_to_millicelsius_overflow(long t, long *ret)
>     
>   • On a 32-bit system:  long  is a 32-bit signed integer with a
>   maximum value of  2,147,483,647 . If the EC hardware returns a bogus
>   or uninitialized positive  u32  value (e.g.,  3,000,000 ), the
>   multiplication  t * MILLIDEGREE_PER_DEGREE  ( 3,000,000 * 1000 =
>   3,000,000,000 ) will exceed  LONG_MAX  and cause a signed integer
>   overflow.                                                           

This is the case I want to handle.

>   • On a 64-bit system:  long  is a 64-bit integer. The maximum
>   possible  u32  value multiplied by  1000  is  4,294,967,295,000 ,
>   which comfortably fits within the 64-bit limit of  9.22 x 10^18 . An
>   overflow here is mathematically impossible.                                                                                                                                                            
And the compiler knows this and optimizes away the overflow checks.

>   
>   ### 2. A Quirky Edge Case on 32-bit
>   
>   If the EC returns a standard error state like  0xFFFFFFFF , the
>   implicit cast from  u32 threshold  to  long t  on a 32-bit system
>   will result in  t = -1 .

This "standard error" state does not apply to these values.
'0' means 'disabled', all other values are normal values.

>   Interestingly, the new  check_mul_overflow(-1, 1000, ret)  check
>   will not trigger, because  -1000  fits perfectly inside a 32-bit
>   long . Instead, it will silently return a bogus value of  -274000 
>   (which corresponds to -274°C). The patch does not actually prevent
>   this specific "incorrect data" case.                                                                                                

This is a bug in my code. I'd like to fix it like below, so the compiler
can optimize this away on 64-bit, too.

                        if (ret == 0) {
+                               if (overflows_type(threshold, long))
+                                       *val = LONG_MAX;
+
                                if (cros_ec_hwmon_kelvin_to_millicelsius_overflow(threshold, val))
                                        *val = LONG_MAX;

>   ### 3.  cros_ec_hwmon_temp_to_millicelsius 
>   
>   For the standard temperature readings (where  temp  is a  u8 ), an
>   overflow is impossible on all architectures.
>   The maximum value of  u8  is 255. When the offset of 200 is added,
>   the maximum base is 455. Multiplying  455 * 1000  is  455,000 ,
>   which easily fits in a 32-bit (and even 16-bit) integer. The patch
>   author is clearly aware of this, which is why the patch asserts its
>   impossibility via  BUILD_BUG() :                                                                                                   
>   
>         if (check_add_overflow(temp, EC_TEMP_SENSOR_OFFSET, &ret))
>             BUILD_BUG();
>     
>         if (cros_ec_hwmon_kelvin_to_millicelsius_overflow(ret, &ret))
>             BUILD_BUG();

That is correct. The idea is again to share one conversion function
between all users to avoid code duplication.

>   ### Conclusion
>   
>   The patch's claim that calculations "can overflow" is accurate, but
>   the scope of the fix is limited strictly to threshold registers
>   running on 32-bit systems, and it will still emit bogus negative
>   temperatures for unsigned integer values larger than  LONG_MAX
>   (such as  0xFFFFFFFF ).

I'll also mention that the overflow only affects 32-bit systems
and that the compiler will optimize away the checks on 64-bit.

Does that make sense?


Thomas

      reply	other threads:[~2026-07-07 16:52 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-30 20:57 [PATCH 0/2] hwmon: (cros_ec) Rework the temperature conversions Thomas Weißschuh
2026-06-30 20:57 ` [PATCH 1/2] hwmon: (cros_ec) Implement custom kelvin to celsius conversions Thomas Weißschuh
2026-06-30 23:07   ` Guenter Roeck
2026-06-30 20:57 ` [PATCH 2/2] hwmon: (cros_ec) Handle temperature conversion overflows Thomas Weißschuh
2026-06-30 23:06   ` Guenter Roeck
2026-07-07 16:52     ` Thomas Weißschuh [this message]

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=2b1c29c8-bf87-4113-ba1e-63e1b1d1ff51@t-8ch.de \
    --to=linux@weissschuh.net \
    --cc=bleung@chromium.org \
    --cc=chrome-platform@lists.linux.dev \
    --cc=groeck@chromium.org \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@roeck-us.net \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox