]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
nptl: Add rseq auxvals
authorMichael Jeanson <mjeanson@efficios.com>
Wed, 10 Jul 2024 19:37:28 +0000 (15:37 -0400)
committerMichael Jeanson <mjeanson@efficios.com>
Fri, 10 Jan 2025 20:19:07 +0000 (20:19 +0000)
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>
sysdeps/nptl/dl-tls_init_tp.c
sysdeps/unix/sysv/linux/dl-parse_auxv.h
sysdeps/unix/sysv/linux/rseq-internal.h
sysdeps/unix/sysv/linux/tst-rseq.c
sysdeps/unix/sysv/linux/tst-rseq.h

index c57738e9f3e95b6b6c6ee90eb722cca64e390630..46478324fc7f1eecfc4ce22c4bf5c9d3ac0222d7 100644 (file)
@@ -46,6 +46,8 @@ rtld_mutex_dummy (pthread_mutex_t *lock)
 
 const unsigned int __rseq_flags;
 
+size_t _rseq_align attribute_hidden;
+
 void
 __tls_pre_init_tp (void)
 {
@@ -99,10 +101,14 @@ __tls_init_tp (void)
   }
 
   {
-    bool do_rseq = true;
-    do_rseq = TUNABLE_GET (rseq, int, NULL);
-    if (rseq_register_current_thread (pd, do_rseq))
-      _rseq_size = RSEQ_AREA_SIZE_INITIAL_USED;
+    /* If the registration fails or is disabled by tunable, the public
+       '__rseq_size' will be set to '0' regardless of the feature size of the
+       allocated rseq area.  An rseq area of at least 32 bytes is always
+       allocated since application code is allowed to check the status of the
+       rseq registration by reading the content of the 'cpu_id' field.  */
+    bool do_rseq = TUNABLE_GET (rseq, int, NULL);
+    if (!rseq_register_current_thread (pd, do_rseq))
+      _rseq_size = 0;
 
 #ifdef RSEQ_SIG
     /* This should be a compile-time constant, but the current
index 7b4427d0a73ce76297339b8c1aa32ffcccb817d3..2d4243734ceca7969d2461fe0b0974428ff1148a 100644 (file)
@@ -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
 }
index a0c244b0cf53350cbb6d03fa79af568eb4279764..6f565581c14cda07535be25c1307c6959a5a6cc5 100644 (file)
 #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
index aced4bd66c850456b4c9f189ecbb5d9ba6ac0566..b152280efff4805b7862c7d3d3a4cd67f08d1820 100644 (file)
@@ -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
index f216d3f7d7be61ddc2650d6efecb745ae92c0c07..15f512a983aa9de564254cbcb293980f6b90179c 100644 (file)
@@ -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)