Skip to content

Commit e355972

Browse files
sean-jcgregkh
authored andcommitted
selftests/rseq: Play nice with binaries statically linked against glibc 2.35+
[ Upstream commit 3bcbc20 ] To allow running rseq and KVM's rseq selftests as statically linked binaries, initialize the various "trampoline" pointers to point directly at the expect glibc symbols, and skip the dlysm() lookups if the rseq size is non-zero, i.e. the binary is statically linked *and* the libc registered its own rseq. Define weak versions of the symbols so as not to break linking against libc versions that don't support rseq in any capacity. The KVM selftests in particular are often statically linked so that they can be run on targets with very limited runtime environments, i.e. test machines. Fixes: 233e667 ("selftests/rseq: Uplift rseq selftests for compatibility with glibc-2.35") Cc: Aaron Lewis <aaronlewis@google.com> Cc: kvm@vger.kernel.org Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson <seanjc@google.com> Message-Id: <20230721223352.2333911-1-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 5656267 commit e355972

File tree

1 file changed

+22
-6
lines changed
  • tools/testing/selftests/rseq

1 file changed

+22
-6
lines changed

tools/testing/selftests/rseq/rseq.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,17 @@
3232
#include "../kselftest.h"
3333
#include "rseq.h"
3434

35-
static const ptrdiff_t *libc_rseq_offset_p;
36-
static const unsigned int *libc_rseq_size_p;
37-
static const unsigned int *libc_rseq_flags_p;
35+
/*
36+
* Define weak versions to play nice with binaries that are statically linked
37+
* against a libc that doesn't support registering its own rseq.
38+
*/
39+
__weak ptrdiff_t __rseq_offset;
40+
__weak unsigned int __rseq_size;
41+
__weak unsigned int __rseq_flags;
42+
43+
static const ptrdiff_t *libc_rseq_offset_p = &__rseq_offset;
44+
static const unsigned int *libc_rseq_size_p = &__rseq_size;
45+
static const unsigned int *libc_rseq_flags_p = &__rseq_flags;
3846

3947
/* Offset from the thread pointer to the rseq area. */
4048
ptrdiff_t rseq_offset;
@@ -108,9 +116,17 @@ int rseq_unregister_current_thread(void)
108116
static __attribute__((constructor))
109117
void rseq_init(void)
110118
{
111-
libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
112-
libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
113-
libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
119+
/*
120+
* If the libc's registered rseq size isn't already valid, it may be
121+
* because the binary is dynamically linked and not necessarily due to
122+
* libc not having registered a restartable sequence. Try to find the
123+
* symbols if that's the case.
124+
*/
125+
if (!*libc_rseq_size_p) {
126+
libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
127+
libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
128+
libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
129+
}
114130
if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p &&
115131
*libc_rseq_size_p != 0) {
116132
/* rseq registration owned by glibc */

0 commit comments

Comments
 (0)