s390/cmpxchg: Fix KASAN stack-out-of-bounds in atomic helpers

The __arch_cmpxchg1, __arch_cmpxchg2, __arch_xchg1, and __arch_xchg2
functions emulate 1-byte and 2-byte atomic operations using 4-byte
cmpxchg instructions, since s390 lacks native 1/2-byte cmpxchg support.

When KASAN is enabled, the READ_ONCE() operations in these functions
trigger stack-out-of-bounds warnings because they perform 4-byte reads
when only 1 or 2 bytes should be accessed.

Mark these functions as __no_sanitize_or_inline to prevent KASAN
instrumentation while maintaining correct functionality.

This resolves the following KASAN error during rust_atomics KUnit tests:

  BUG: KASAN: stack-out-of-bounds in rust_helper_atomic_i8_xchg+0xb2/0xc0
  Read of size 4 at addr 001bff7ffdbefcf0 by task kunit_try_catch/142

Reported-by: Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
Link: https://lore.kernel.org/rust-for-linux/CANiq72m4GVWFYqnxNtCHTPu7XcGewHB5LNwOoayTfnXs9pPbNg@mail.gmail.com/
Suggested-by: Gary Guo <gary@garyguo.net>
Link: https://lore.kernel.org/rust-for-linux/DITFTAVVHTNQ.380OHUHGTOI6M@garyguo.net/
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Acked-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
This commit is contained in:
Jan Polensky 2026-06-01 19:46:24 +02:00 committed by Alexander Gordeev
parent 71247e71a4
commit a423d94fa1

View File

@ -35,7 +35,7 @@ static __always_inline u64 __csg_asm(u64 ptr, u64 old, u64 new)
return old;
}
static inline u8 __arch_cmpxchg1(u64 ptr, u8 old, u8 new)
static __no_sanitize_or_inline u8 __arch_cmpxchg1(u64 ptr, u8 old, u8 new)
{
union {
u8 b[4];
@ -58,7 +58,7 @@ static inline u8 __arch_cmpxchg1(u64 ptr, u8 old, u8 new)
return old;
}
static inline u16 __arch_cmpxchg2(u64 ptr, u16 old, u16 new)
static __no_sanitize_or_inline u16 __arch_cmpxchg2(u64 ptr, u16 old, u16 new)
{
union {
u16 b[2];
@ -173,7 +173,7 @@ static __always_inline u64 __arch_cmpxchg(u64 ptr, u64 old, u64 new, int size)
void __xchg_called_with_bad_pointer(void);
static inline u8 __arch_xchg1(u64 ptr, u8 x)
static __no_sanitize_or_inline u8 __arch_xchg1(u64 ptr, u8 x)
{
int shift = (3 ^ (ptr & 3)) << 3;
u32 mask, old, new;
@ -188,7 +188,7 @@ static inline u8 __arch_xchg1(u64 ptr, u8 x)
return old >> shift;
}
static inline u16 __arch_xchg2(u64 ptr, u16 x)
static __no_sanitize_or_inline u16 __arch_xchg2(u64 ptr, u16 x)
{
int shift = (2 ^ (ptr & 2)) << 3;
u32 mask, old, new;