All of lore.kernel.org
 help / color / mirror / Atom feed
From: Helge Deller <deller@gmx.de>
To: linux-kernel@vger.kernel.org, linux-parisc@vger.kernel.org,
	Andrew Morton <akpm@linux-foundation.org>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Chanho Min <chanho.min@lge.com>,
	Geert Uytterhoeven <geert@linux-m68k.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Subject: [PATCH] lib/clz_ctz.c: Fix __clzdi2() and __ctzdi2() for 32-bit kernels
Date: Fri, 25 Aug 2023 21:50:33 +0200	[thread overview]
Message-ID: <ZOkGCSNr0VN2VIJJ@p100> (raw)

The gcc compiler translates on some architectures the 64-bit
__builtin_clzll() function to a call to the libgcc function
__clzdi2(), which should take a 64-bit parameter on 32- and 64-bit
platforms.

But in the current kernel code, the built-in __clzdi2() function is
defined to operate (wrongly) on 32-bit parameters if BITS_PER_LONG == 32,
thus the return values on 32-bit kernels are in the range from
[0..31] instead of the expected [0..63] range.

This patch fixes the in-kernel functions __clzdi2() and __ctzdi2() to
take a 64-bit parameter on 32-bit kernels as well, thus it makes the
functions identical for 32- and 64-bit kernels.

This bug went unnoticed since kernel 3.11 for over 10 years, and
here are some possible reasons for that:

a) Some architectures have assembly instructions to count the bits
   and which are used instead of calling __clzdi2(), e.g. on x86 the
   bsr instruction and on ppc cntlz is used. On such architectures
   the wrong __clzdi2() implementation isn't used and as such the
   bug has no effect and won't be noticed.

b) Some architectures link to libgcc.a, and the in-kernel weak
   functions get replaced by the correct 64-bit variants from libgcc.a.

c) __builtin_clzll() and __clzdi2() doesn't seem to be used in many
   places in the kernel, and most likely only in uncritical functions,
   e.g. when printing hex values via seq_put_hex_ll(). The wrong return
   value will still print the correct number, but just in a wrong formatting
   (e.g. with too many leading zeroes).

d) 32-bit kernels aren't used that much any longer, so they are less
   tested.

A trivial testcase to verify if the currently running 32-bit kernel
is affected by the bug is to look at the output of /proc/self/maps:

Here the kernel uses a correct implementation of __clzdi2():
root@debian:~# cat /proc/self/maps
00010000-00019000 r-xp 00000000 08:05 787324     /usr/bin/cat
00019000-0001a000 rwxp 00009000 08:05 787324     /usr/bin/cat
0001a000-0003b000 rwxp 00000000 00:00 0          [heap]
f7551000-f770d000 r-xp 00000000 08:05 794765     /usr/lib/hppa-linux-gnu/libc.so.6
...

and this kernel uses the broken implementation of __clzdi2():
root@debian:~# cat /proc/self/maps
0000000010000-0000000019000 r-xp 00000000 000000008:000000005 787324  /usr/bin/cat
0000000019000-000000001a000 rwxp 000000009000 000000008:000000005 787324  /usr/bin/cat
000000001a000-000000003b000 rwxp 00000000 00:00 0  [heap]
00000000f73d1000-00000000f758d000 r-xp 00000000 000000008:000000005 794765  /usr/lib/hppa-linux-gnu/libc.so.6
...

Signed-off-by: Helge Deller <deller@gmx.de>
Fixes: 4df87bb7b6a22 ("lib: add weak clz/ctz functions")
Cc: Chanho Min <chanho.min@lge.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: <stable@vger.kernel.org> # v3.11+

diff --git a/lib/clz_ctz.c b/lib/clz_ctz.c
index 0d3a686b5ba2..fb8c0c5c2bd2 100644
--- a/lib/clz_ctz.c
+++ b/lib/clz_ctz.c
@@ -28,36 +28,16 @@ int __weak __clzsi2(int val)
 }
 EXPORT_SYMBOL(__clzsi2);
 
-int __weak __clzdi2(long val);
-int __weak __ctzdi2(long val);
-#if BITS_PER_LONG == 32
-
-int __weak __clzdi2(long val)
+int __weak __clzdi2(u64 val);
+int __weak __clzdi2(u64 val)
 {
-	return 32 - fls((int)val);
+	return 64 - fls64(val);
 }
 EXPORT_SYMBOL(__clzdi2);
 
-int __weak __ctzdi2(long val)
+int __weak __ctzdi2(u64 val);
+int __weak __ctzdi2(u64 val)
 {
-	return __ffs((u32)val);
+	return __ffs64(val);
 }
 EXPORT_SYMBOL(__ctzdi2);
-
-#elif BITS_PER_LONG == 64
-
-int __weak __clzdi2(long val)
-{
-	return 64 - fls64((u64)val);
-}
-EXPORT_SYMBOL(__clzdi2);
-
-int __weak __ctzdi2(long val)
-{
-	return __ffs64((u64)val);
-}
-EXPORT_SYMBOL(__ctzdi2);
-
-#else
-#error BITS_PER_LONG not 32 or 64
-#endif

             reply	other threads:[~2023-08-25 19:51 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-25 19:50 Helge Deller [this message]
2023-08-25 20:25 ` [PATCH] lib/clz_ctz.c: Fix __clzdi2() and __ctzdi2() for 32-bit kernels Linus Torvalds
2023-08-25 20:43   ` Linus Torvalds
2023-08-25 21:01     ` Nick Desaulniers
2023-08-25 22:33       ` Bill Wendling
2023-08-25 22:57         ` Bill Wendling
2023-08-25 23:34           ` Linus Torvalds
2023-08-26  0:08             ` Bill Wendling
2023-08-26  0:52             ` Nick Desaulniers
2023-08-26  1:07               ` Linus Torvalds
2023-08-26  3:17                 ` Fangrui Song
2023-08-28  7:33                 ` Geert Uytterhoeven
2023-08-28 16:24                   ` Linus Torvalds
2023-08-28 20:13                     ` Nick Desaulniers
2023-08-28 20:09                   ` Nick Desaulniers
2023-08-28 20:08                 ` Nick Desaulniers
2023-08-28 10:53     ` David Laight
2023-08-28 16:30       ` Linus Torvalds
2023-08-28 20:14         ` Nick Desaulniers
2023-08-28 20:10       ` Nick Desaulniers

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=ZOkGCSNr0VN2VIJJ@p100 \
    --to=deller@gmx.de \
    --cc=akpm@linux-foundation.org \
    --cc=chanho.min@lge.com \
    --cc=geert@linux-m68k.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-parisc@vger.kernel.org \
    --cc=torvalds@linux-foundation.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.