On Wed, 26 Feb 2025 at 09:10, Christophe JAILLET <christophe.jaillet@xxxxxxxxxx> wrote: > > Le 26/02/2025 à 08:28, Daniel Vacek a écrit : > > On Tue, 25 Feb 2025 at 22:10, Christophe JAILLET > > <christophe.jaillet-39ZsbGIQGT5GWvitb5QawA@xxxxxxxxxxxxxxxx> wrote: > >> > >> Le 25/02/2025 à 21:17, Easwar Hariharan a écrit : > >>> Commit b35108a51cf7 ("jiffies: Define secs_to_jiffies()") introduced > >>> secs_to_jiffies(). As the value here is a multiple of 1000, use > >>> secs_to_jiffies() instead of msecs_to_jiffies() to avoid the multiplication > >>> > >>> This is converted using scripts/coccinelle/misc/secs_to_jiffies.cocci with > >>> the following Coccinelle rules: > >>> > >>> @depends on patch@ expression E; @@ > >>> > >>> -msecs_to_jiffies(E * 1000) > >>> +secs_to_jiffies(E) > >>> > >>> @depends on patch@ expression E; @@ > >>> > >>> -msecs_to_jiffies(E * MSEC_PER_SEC) > >>> +secs_to_jiffies(E) > >>> > >>> While here, remove the no-longer necessary check for range since there's > >>> no multiplication involved. > >> > >> I'm not sure this is correct. > >> Now you multiply by HZ and things can still overflow. > > > > This does not deal with any additional multiplications. If there is an > > overflow, it was already there before to begin with, IMO. > > > >> Hoping I got casting right: > > > > Maybe not exactly? See below... > > > >> #define MSEC_PER_SEC 1000L > >> #define HZ 100 > >> > >> > >> #define secs_to_jiffies(_secs) (unsigned long)((_secs) * HZ) > >> > >> static inline unsigned long _msecs_to_jiffies(const unsigned int m) > >> { > >> return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); > >> } > >> > >> int main() { > >> > >> int n = INT_MAX - 5; > >> > >> printf("res = %ld\n", secs_to_jiffies(n)); > >> printf("res = %ld\n", _msecs_to_jiffies(1000 * n)); > > > > I think the format should actually be %lu giving the below results: > > > > res = 18446744073709551016 > > res = 429496130 > > > > Which is still wrong nonetheless. But here, *both* results are wrong > > as the expected output should be 214748364200 which you'll get with > > the correct helper/macro. > > > > But note another thing, the 1000 * (INT_MAX - 5) already overflows > > even before calling _msecs_to_jiffies(). See? > > Agreed and intentional in my test C code. > > That is the point. > > The "if (result.uint_32 > INT_MAX / 1000)" in the original code was > handling such values. I see. But that was rather an unrelated side-effect. Still you're right, it needs to be handled carefully not to remove additional guarantees which were implied unintentionally. At least in places where these were provided in the first place. > > > > Now, you'll get that mentioned correct result with: > > > > #define secs_to_jiffies(_secs) ((unsigned long)(_secs) * HZ) > > Not looked in details, but I think I would second on you on this, in > this specific example. Not sure if it would handle all possible uses of > secs_to_jiffies(). Yeah, I was referring only in context of the example you presented, not for the rest of the kernel. Sorry about the confusion. > But it is not how secs_to_jiffies() is defined up to now. See [1]. > > [1]: > https://elixir.bootlin.com/linux/v6.14-rc4/source/include/linux/jiffies.h#L540 > > > > > Still, why unsigned? What if you wanted to convert -5 seconds to jiffies? > > See commit bb2784d9ab495 which added the cast. Hmmm, fishy. Maybe a function would be better than a macro? > > > >> return 0; > >> } > >> > >> > >> gives : > >> > >> res = -600 > >> res = 429496130 > >> > >> with msec, the previous code would catch the overflow, now it overflows > >> silently. > > > > What compiler options are you using? I'm not getting any warnings. > > I mean, with: > if (result.uint_32 > INT_MAX / 1000) > goto out_of_range; > the overflow would be handled *at runtime*. Got it. But that may still fail if you configure HZ to 5000 or anything above 1000. Not that anyone should go this way but... > Without such a check, an unexpected value could be stored in > opt->lock_timeout. > > I think that a test is needed and with secs_to_jiffies(), I tentatively > proposed: > if (result.uint_32 > INT_MAX / HZ) > goto out_of_range; Right, that should correctly handle any HZ value. Looks good to me. > CJ > > > > >> untested, but maybe: > >> if (result.uint_32 > INT_MAX / HZ) > >> goto out_of_range; > >> > >> ? > >> > >> CJ > >> > > ...