From: Adhemerval Zanella Date: Wed, 17 Jun 2026 14:25:47 +0000 (-0300) Subject: s390: Prevent hoisting the thread-pointer read in THREAD_SET_STACK_GUARD (BZ 34297) X-Git-Tag: glibc-2.44~55 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=28c3a25bc249ab4f20d09fc2a8694f6bca9155dd;p=thirdparty%2Fglibc.git s390: Prevent hoisting the thread-pointer read in THREAD_SET_STACK_GUARD (BZ 34297) THREAD_SET_STACK_GUARD reads the thread pointer via THREAD_SELF (__builtin_thread_pointer), which the compiler treats as invariant. In the static startup path the thread pointer is installed by the __libc_setup_tls call that immediately precedes the guard store, so the read must stay below it. The existing barrier only clobbered the access registers a0/a1, which creates no dependency on the call, so the compiler could move the whole barrier and read above __libc_setup_tls. This is sensitive to instruction scheduling and recent TLS startup changes exposed it on s390x. Add a "memory" clobber to the barrier so it is tied to the call's memory effects and cannot be hoisted above it. The macro is shared with the dynamic loader, so both startup paths are covered. I checked on s390x-linux-gnu build for arch5, arch8, arch9, and arch11 by running the elf tests on qemu system (kernel 6.1.0). Reviewed-by: Stefan Liebler --- diff --git a/sysdeps/s390/nptl/tls.h b/sysdeps/s390/nptl/tls.h index 41fd473d14..6ecaa24384 100644 --- a/sysdeps/s390/nptl/tls.h +++ b/sysdeps/s390/nptl/tls.h @@ -131,7 +131,7 @@ typedef struct #define THREAD_SET_STACK_GUARD(value) \ do \ { \ - __asm__ __volatile__ ("" : : : "a0", "a1"); \ + __asm__ __volatile__ ("" : : : "a0", "a1", "memory"); \ THREAD_SETMEM (THREAD_SELF, header.stack_guard, value); \ } \ while (0)