lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <0cbe7ab8-bd87-b5f7-0513-07c82a7e76c9@loongson.cn>
Date: Mon, 7 Apr 2025 18:52:10 +0800
From: Tiezhu Yang <yangtiezhu@...ngson.cn>
To: Josh Poimboeuf <jpoimboe@...nel.org>
Cc: Philip Li <philip.li@...el.com>, kernel test robot <lkp@...el.com>,
 Guenter Roeck <linux@...ck-us.net>, oe-kbuild-all@...ts.linux.dev,
 Andrew Morton <akpm@...ux-foundation.org>,
 Linux Memory Management List <linux-mm@...ck.org>,
 Alessandro Carminati <acarmina@...hat.com>,
 Peter Zijlstra <peterz@...radead.org>, linux-kernel@...r.kernel.org,
 loongarch@...ts.linux.dev
Subject: Re: [linux-next:master 12681/13861] drivers/i2c/i2c-core-base.o:
 warning: objtool: __i2c_transfer+0x120: stack state mismatch: reg1[24]=-1+0
 reg2[24]=-2-24

On 04/03/2025 10:37 PM, Josh Poimboeuf wrote:
> On Thu, Apr 03, 2025 at 05:35:51PM +0800, Tiezhu Yang wrote:
>> On 04/02/2025 03:45 AM, Josh Poimboeuf wrote:
>>> On Tue, Apr 01, 2025 at 12:38:37PM +0800, Philip Li wrote:
>>>> On Tue, Apr 01, 2025 at 10:44:57AM +0800, kernel test robot wrote:
>>>>> tree:   https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
>>>>> head:   405e2241def89c88f008dcb899eb5b6d4be8b43c
>>>>> commit: 9016dad4dca4bbe61c48ffd5a273cad980caa0d1 [12681/13861] loongarch: add support for suppressing warning backtraces
>>>>> config: loongarch-randconfig-001-20250401 (https://download.01.org/0day-ci/archive/20250401/202504011011.jyZ6NtXx-lkp@intel.com/config)
>>>>> compiler: loongarch64-linux-gcc (GCC) 14.2.0
>>>>> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250401/202504011011.jyZ6NtXx-lkp@intel.com/reproduce)
>>>>>
>>>>> If you fix the issue in a separate patch/commit (i.e. not just a new version of
>>>>> the same patch/commit), kindly add following tags
>>>>> | Reported-by: kernel test robot <lkp@...el.com>
>>>>> | Closes: https://lore.kernel.org/oe-kbuild-all/202504011011.jyZ6NtXx-lkp@intel.com/
>>>>>
>>>>> All warnings (new ones prefixed by >>):
>>>>>
>>>>>>> drivers/i2c/i2c-core-base.o: warning: objtool: __i2c_transfer+0x120: stack state mismatch: reg1[24]=-1+0 reg2[24]=-2-24
>>>
>>> Tiezhu, this looks like a loongarch GCC bug with asm goto, or am I
>>> confused?  See analysis below.
>>
>> This is related with GCC optimization "-fshrink-wrap" which is default y
>> on LoongArch, use "-fno-shrink-wrap" can avoid such issues, like this:
>
> As I showed, it looks like an actual runtime bug, not an objtool false
> positive.  Disabling it only for CONFIG_OBJTOOLonly wouldn't fix that.

Here are my thoughts:

(1) -fshrink-wrap

The prologue may perform a variety of target dependent tasks such
as saving callee-saved registers, saving the return address, etc.

On some targets some of these tasks may be independent of others
and thus may be shrink-wrapped separately. These independent tasks
are referred to as components and are handled generically by the
target independent parts of GCC.

The initialization is not done as frequently on execution paths
where this would unnecessary.

"-fshrink-wrap" is enabled by default at -O and higher, will emit
function prologues only before parts of the function that need it,
rather than at the top of the function.

https://gcc.gnu.org/onlinedocs/gccint/Shrink-wrapping-separate-components.html
https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fshrink-wrap

There is a potential execution path with only using s0 and ra
(without using s1, s2, s3, etc): 2d58-->2d70-->2f88-->2e78-->2e84

0000000000002d58 <__i2c_transfer>:
     2d58:       02fe8063        addi.d          $sp, $sp, -96
     2d5c:       29c14077        st.d            $s0, $sp, 80
     2d60:       29c16061        st.d            $ra, $sp, 88
     2d64:       28c0408c        ld.d            $t0, $a0, 16
     2d68:       00150097        or              $s0, $a0, $zero
     2d6c:       2600018c        ldptr.d         $t0, $t0, 0
     2d70:       40021980        beqz            $t0, 536        # 2f88 
<.LVL1023>
...
0000000000002f88 <.LVL1023>:
     2f88:       1a000006        pcalau12i       $a2, 0

0000000000002f8c <.LVL1024>:
     2f8c:       1a000004        pcalau12i       $a0, 0

0000000000002f90 <.LVL1025>:
     2f90:       02c00084        addi.d          $a0, $a0, 0
     2f94:       02c1c2e5        addi.d          $a1, $s0, 112

0000000000002f98 <.LVL1026>:
     2f98:       02c000c6        addi.d          $a2, $a2, 0
     2f9c:       54000000        bl              0       # 2f9c 
<.LVL1026+0x4>
 >
0000000000002fa0 <.LVL1027>:
     2fa0:       02be8404        addi.w          $a0, $zero, -95
     2fa4:       53fed7ff        b               -300    # 2e78 <.L845>
...
0000000000002e78 <.L845>:
     2e78:       28c16061        ld.d            $ra, $sp, 88
     2e7c:       28c14077        ld.d            $s0, $sp, 80

0000000000002e80 <.LVL994>:
     2e80:       02c18063        addi.d          $sp, $sp, 96
     2e84:       4c000020        jirl            $zero, $ra, 0

 From this point of view, it seems that there is no problem for the
generated instructions of the current code, it is not a runtime bug,
just a GCC optimization.

(2) Analysis

In fact, the generated objtool warning is because the break instruction
(2ee8) which is before the restoring s1 instruction (2eec) is annotated
as dead end.

0000000000002d58 <__i2c_transfer>:
     2d58:       02fe8063        addi.d          $sp, $sp, -96
     2d5c:       29c14077        st.d            $s0, $sp, 80
     2d60:       29c16061        st.d            $ra, $sp, 88
     2d64:       28c0408c        ld.d            $t0, $a0, 16
     2d68:       00150097        or              $s0, $a0, $zero
     2d6c:       2600018c        ldptr.d         $t0, $t0, 0
     2d70:       40021980        beqz            $t0, 536        # 2f88 
<.LVL1023>
     2d74:       29c12078        st.d            $s1, $sp, 72
     2d78:       001500b8        or              $s1, $a1, $zero

0000000000002d7c <.LBB2114>:
     2d7c:       400150a0        beqz            $a1, 336        # 2ecc 
<.LVL999+0x4>
...
     2ecc:       1a000004        pcalau12i       $a0, 0

0000000000002ed0 <.LVL1000>:
     2ed0:       02c00084        addi.d          $a0, $a0, 0
     2ed4:       02c5a084        addi.d          $a0, $a0, 360
     2ed8:       54000000        bl              0       # 2ed8 
<.LVL1000+0x8>

0000000000002edc <.LVL1001>:
     2edc:       0015008c        or              $t0, $a0, $zero
     2ee0:       02bfa804        addi.w          $a0, $zero, -22
     2ee4:       44003d80        bnez            $t0, 60 # 2f20 
<.LVL1008+0x8>

0000000000002ee8 <.L10001^B7>:
     2ee8:       002a0001        break           0x1
     2eec:       28c12078        ld.d            $s1, $sp, 72

0000000000002ef0 <.LVL1002>:
     2ef0:       53ff8bff        b               -120    # 2e78 <.L845>

This issue is introduced by the following changes:

  #define __WARN_FLAGS(flags)					\
  do {								\
  	instrumentation_begin();				\
-	__BUG_FLAGS(BUGFLAG_WARNING|(flags), ANNOTATE_REACHABLE(10001b));\
+	if (!KUNIT_IS_SUPPRESSED_WARNING(__func__))			\
+		__BUG_FLAGS(BUGFLAG_WARNING|(flags), ANNOTATE_REACHABLE(10001b));\
  	instrumentation_end();					\
  } while (0)

of commit e61a8b4b0d83 ("loongarch: add support for suppressing warning
backtraces") in the linux-next.git.

(3) -fno-shrink-wrap

"-fno-shrink-wrap" will save callee-saved registers and the return
address together as a whole block in the prologue at the top of the
function, and also restores them together as a whole block in the
epilogue.

0000000000002b38 <__i2c_transfer>:
     2b38:       02fe8063        addi.d          $sp, $sp, -96
     2b3c:       29c14077        st.d            $s0, $sp, 80
     2b40:       29c12078        st.d            $s1, $sp, 72
     2b44:       29c10079        st.d            $s2, $sp, 64
     2b48:       29c16061        st.d            $ra, $sp, 88
     2b4c:       29c0e07a        st.d            $s3, $sp, 56
     2b50:       29c0c07b        st.d            $s4, $sp, 48
     2b54:       29c0a07c        st.d            $s5, $sp, 40
     2b58:       29c0807d        st.d            $s6, $sp, 32
     2b5c:       29c0607e        st.d            $s7, $sp, 24
     2b60:       29c0407f        st.d            $s8, $sp, 16
...
0000000000002c38 <.L747>:
     2c38:       28c16061        ld.d            $ra, $sp, 88
     2c3c:       28c14077        ld.d            $s0, $sp, 80

0000000000002c40 <.LVL937>:
     2c40:       28c12078        ld.d            $s1, $sp, 72
     2c44:       28c10079        ld.d            $s2, $sp, 64

0000000000002c48 <.LVL938>:
     2c48:       28c0e07a        ld.d            $s3, $sp, 56
     2c4c:       28c0c07b        ld.d            $s4, $sp, 48
     2c50:       28c0a07c        ld.d            $s5, $sp, 40
     2c54:       28c0807d        ld.d            $s6, $sp, 32
     2c58:       28c0607e        ld.d            $s7, $sp, 24
     2c5c:       28c0407f        ld.d            $s8, $sp, 16
     2c60:       02c18063        addi.d          $sp, $sp, 96
     2c64:       4c000020        jirl            $zero, $ra, 0

(4) Solution 1
One way is to annotate __BUG_ENTRY() as reachable whether
KUNIT_IS_SUPPRESSED_WARNING() is true or false, like this:

---8<---
diff --git a/arch/loongarch/include/asm/bug.h 
b/arch/loongarch/include/asm/bug.h
index b79ff6696ce6..e41ebeaba204 100644
--- a/arch/loongarch/include/asm/bug.h
+++ b/arch/loongarch/include/asm/bug.h
@@ -60,8 +60,9 @@
  #define __WARN_FLAGS(flags)                                    \
  do {                                                           \
         instrumentation_begin();                                \
-       if (!KUNIT_IS_SUPPRESSED_WARNING(__func__))                     \
-               __BUG_FLAGS(BUGFLAG_WARNING|(flags), 
ANNOTATE_REACHABLE(10001b));\
+       if (!KUNIT_IS_SUPPRESSED_WARNING(__func__))             \
+               __BUG_FLAGS(BUGFLAG_WARNING|(flags), "");       \
+       __BUG_FLAGS(0, ANNOTATE_REACHABLE(10001b));             \
         instrumentation_end();                                  \
  } while (0)

(5) Solution 2
The other way is to use "-fno-shrink-wrap" to aovid such issue under
CONFIG_OBJTOOL at compile-time, like this:

---8<---
diff --git a/arch/loongarch/Makefile b/arch/loongarch/Makefile
index 0304eabbe606..2d5529322357 100644
--- a/arch/loongarch/Makefile
+++ b/arch/loongarch/Makefile
@@ -106,6 +106,7 @@ KBUILD_CFLAGS                       +=
-mannotate-tablejump
   else
   KBUILD_CFLAGS                  += -fno-jump-tables # keep
compatibility with older compilers
   endif
+KBUILD_CFLAGS                  += -fno-shrink-wrap
   endif

   KBUILD_RUSTFLAGS               +=
--target=loongarch64-unknown-none-softfloat -Ccode-model=small

If you have more suggestion, please let me know.

Thanks,
Tiezhu


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ