Skip to content

Commit 3bcbc20

Browse files
sean-jcbonzini
authored andcommitted
selftests/rseq: Play nice with binaries statically linked against glibc 2.35+
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>
1 parent b439eb8 commit 3bcbc20

1 file changed

Lines changed: 22 additions & 6 deletions

File tree

  • tools/testing/selftests/rseq

tools/testing/selftests/rseq/rseq.c

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

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

4149
/* Offset from the thread pointer to the rseq area. */
4250
ptrdiff_t rseq_offset;
@@ -155,9 +163,17 @@ unsigned int get_rseq_feature_size(void)
155163
static __attribute__((constructor))
156164
void rseq_init(void)
157165
{
158-
libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
159-
libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
160-
libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
166+
/*
167+
* If the libc's registered rseq size isn't already valid, it may be
168+
* because the binary is dynamically linked and not necessarily due to
169+
* libc not having registered a restartable sequence. Try to find the
170+
* symbols if that's the case.
171+
*/
172+
if (!*libc_rseq_size_p) {
173+
libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
174+
libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
175+
libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
176+
}
161177
if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p &&
162178
*libc_rseq_size_p != 0) {
163179
/* rseq registration owned by glibc */

0 commit comments

Comments
 (0)