aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix
diff options
context:
space:
mode:
authorMichael Jeanson <mjeanson@efficios.com>2024-07-10 15:37:28 -0400
committerMichael Jeanson <mjeanson@efficios.com>2025-01-10 20:19:07 +0000
commitc813c1490d5d8640a94fced10fc7674a48737b96 (patch)
tree36b9f24bfee314322a72de8b0077b324dbb64055 /sysdeps/unix
parent4a9a8a50981e2a3e0a04ef4c7ad7c26807c18161 (diff)
downloadglibc-c813c1490d5d8640a94fced10fc7674a48737b96.zip
glibc-c813c1490d5d8640a94fced10fc7674a48737b96.tar.gz
glibc-c813c1490d5d8640a94fced10fc7674a48737b96.tar.bz2
nptl: Add rseq auxvals
Get the rseq feature size and alignment requirement from the auxiliary vector for use inside the dynamic loader. Use '__rseq_size' directly to store the feature size. If the main thread registration fails or is disabled by tunable, reset the value to 0. This will be used in the TLS block allocator to compute the size and alignment of the rseq area block for the extended ABI support. Signed-off-by: Michael Jeanson <mjeanson@efficios.com> Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Reviewed-by: Florian Weimer <fweimer@redhat.com>
Diffstat (limited to 'sysdeps/unix')
-rw-r--r--sysdeps/unix/sysv/linux/dl-parse_auxv.h13
-rw-r--r--sysdeps/unix/sysv/linux/rseq-internal.h24
-rw-r--r--sysdeps/unix/sysv/linux/tst-rseq.c6
-rw-r--r--sysdeps/unix/sysv/linux/tst-rseq.h1
4 files changed, 39 insertions, 5 deletions
diff --git a/sysdeps/unix/sysv/linux/dl-parse_auxv.h b/sysdeps/unix/sysv/linux/dl-parse_auxv.h
index 7b4427d..2d42437 100644
--- a/sysdeps/unix/sysv/linux/dl-parse_auxv.h
+++ b/sysdeps/unix/sysv/linux/dl-parse_auxv.h
@@ -21,6 +21,7 @@
#include <fpu_control.h>
#include <ldsodefs.h>
#include <link.h>
+#include <rseq-internal.h>
typedef ElfW(Addr) dl_parse_auxv_t[AT_MINSIGSTKSZ + 1];
@@ -59,5 +60,17 @@ void _dl_parse_auxv (ElfW(auxv_t) *av, dl_parse_auxv_t auxv_values)
GLRO(dl_sysinfo) = auxv_values[AT_SYSINFO];
#endif
+ /* Get the rseq feature size, with a minimum of RSEQ_AREA_SIZE_INITIAL_USED
+ (20) for kernels that don't have AT_RSEQ_FEATURE_SIZE. Limit the feature
+ size to RSEQ_AREA_SIZE_MAX_USED (28) which fits the rseq area in 'struct
+ pthread' and represents the maximum feature size of currently released
+ kernels. Since no kernels currently cross the 32 bytes of the original
+ ABI, the semantics of a feature size of 32 or more are still undetermined.
+ */
+ _rseq_size = MIN (MAX (auxv_values[AT_RSEQ_FEATURE_SIZE],
+ RSEQ_AREA_SIZE_INITIAL_USED),
+ RSEQ_AREA_SIZE_MAX_USED);
+ _rseq_align = MAX (auxv_values[AT_RSEQ_ALIGN], RSEQ_MIN_ALIGN);
+
DL_PLATFORM_AUXV
}
diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
index a0c244b..6f56558 100644
--- a/sysdeps/unix/sysv/linux/rseq-internal.h
+++ b/sysdeps/unix/sysv/linux/rseq-internal.h
@@ -25,13 +25,31 @@
#include <stdio.h>
#include <sys/rseq.h>
-/* 32 is the initially required value for the area size. The
- actually used rseq size may be less (20 bytes initially). */
+/* Minimum size of the rseq area allocation required by the syscall. The
+ actually used rseq feature size may be less (20 bytes initially). */
#define RSEQ_AREA_SIZE_INITIAL 32
+
+/* Minimum used feature size of the rseq area. */
#define RSEQ_AREA_SIZE_INITIAL_USED 20
-/* The variables are in .data.relro but are not yet write-protected. */
+/* Maximum currently used feature size of the rseq area. */
+#define RSEQ_AREA_SIZE_MAX_USED 28
+
+/* Minimum alignment of the rseq area. */
+#define RSEQ_MIN_ALIGN 32
+
+/* Alignment requirement of the rseq area.
+ Populated from the auxiliary vector with a minimum of '32'.
+ In .data.relro but not yet write-protected. */
+extern size_t _rseq_align attribute_hidden;
+
+/* Size of the active features in the rseq area.
+ Populated from the auxiliary vector with a minimum of '20'.
+ In .data.relro but not yet write-protected. */
extern unsigned int _rseq_size attribute_hidden;
+
+/* Offset from the thread pointer to the rseq area.
+ In .data.relro but not yet write-protected. */
extern ptrdiff_t _rseq_offset attribute_hidden;
#ifdef RSEQ_SIG
diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c
index aced4bd..b152280 100644
--- a/sysdeps/unix/sysv/linux/tst-rseq.c
+++ b/sysdeps/unix/sysv/linux/tst-rseq.c
@@ -38,13 +38,15 @@ static void
do_rseq_main_test (void)
{
struct pthread *pd = THREAD_SELF;
+ size_t rseq_feature_size = MIN (MAX (getauxval (AT_RSEQ_FEATURE_SIZE),
+ RSEQ_AREA_SIZE_INITIAL_USED),
+ RSEQ_AREA_SIZE_MAX_USED);
TEST_VERIFY_EXIT (rseq_thread_registered ());
TEST_COMPARE (__rseq_flags, 0);
TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset
== (char *) &pd->rseq_area);
- /* The current implementation only supports the initial size. */
- TEST_COMPARE (__rseq_size, 20);
+ TEST_COMPARE (__rseq_size, rseq_feature_size);
}
static void
diff --git a/sysdeps/unix/sysv/linux/tst-rseq.h b/sysdeps/unix/sysv/linux/tst-rseq.h
index f216d3f..15f512a 100644
--- a/sysdeps/unix/sysv/linux/tst-rseq.h
+++ b/sysdeps/unix/sysv/linux/tst-rseq.h
@@ -23,6 +23,7 @@
#include <syscall.h>
#include <sys/rseq.h>
#include <tls.h>
+#include <rseq-internal.h>
static inline bool
rseq_thread_registered (void)