hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/tools/testing/selftests/rseq/rseq.c
....@@ -29,12 +29,22 @@
2929 #include <dlfcn.h>
3030 #include <stddef.h>
3131
32
+#include <linux/compiler.h>
33
+
3234 #include "../kselftest.h"
3335 #include "rseq.h"
3436
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;
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;
3848
3949 /* Offset from the thread pointer to the rseq area. */
4050 ptrdiff_t rseq_offset;
....@@ -108,10 +118,19 @@
108118 static __attribute__((constructor))
109119 void rseq_init(void)
110120 {
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");
114
- if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p) {
121
+ /*
122
+ * If the libc's registered rseq size isn't already valid, it may be
123
+ * because the binary is dynamically linked and not necessarily due to
124
+ * libc not having registered a restartable sequence. Try to find the
125
+ * symbols if that's the case.
126
+ */
127
+ if (!*libc_rseq_size_p) {
128
+ libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
129
+ libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
130
+ libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
131
+ }
132
+ if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p &&
133
+ *libc_rseq_size_p != 0) {
115134 /* rseq registration owned by glibc */
116135 rseq_offset = *libc_rseq_offset_p;
117136 rseq_size = *libc_rseq_size_p;