diff mbox series

[RFC,v11,01/17] elf: Add rseq auxvals

Message ID 20240801-rseq-abi-v11-split-v11-1-b7bbc0138bfd@efficios.com
State New
Headers show
Series Add rseq extensible ABI support | expand

Commit Message

Michael Jeanson Aug. 2, 2024, 7:02 p.m. UTC
Get the rseq feature size and alignment requirement from the auxiliary
vector for use inside the dynamic loader.

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 and at
thread creation to determine the size of the rseq registration.

Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
---
Open questions:
- Should '_dl_rseq_feature_size' and '_dl_rseq_align' be in GLRO? If not
  where else?
- Since RSEQ is Linux specific, should the changes in 'elf/' and
  'sysdeps/generic/' be moved to 'sysdeps/unix/sysv/linux/'? If so, I'm
  unsure how it would work for GLRO variables.
---
 elf/dl-support.c                        | 8 ++++++++
 elf/rtld_static_init.c                  | 6 ++++++
 sysdeps/generic/ldsodefs.h              | 8 ++++++++
 sysdeps/unix/sysv/linux/dl-parse_auxv.h | 5 +++++
 sysdeps/unix/sysv/linux/dl-sysdep.c     | 2 ++
 sysdeps/unix/sysv/linux/rseq-internal.h | 6 ++++++
 6 files changed, 35 insertions(+)

Comments

Florian Weimer Aug. 3, 2024, 2:41 p.m. UTC | #1
* Michael Jeanson:

> Get the rseq feature size and alignment requirement from the auxiliary
> vector for use inside the dynamic loader.
>
> 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 and at
> thread creation to determine the size of the rseq registration.
>
> Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
> ---
> Open questions:
> - Should '_dl_rseq_feature_size' and '_dl_rseq_align' be in GLRO? If not
>   where else?

I don't thunk we need _dl_rseq_feature_size anymore, you can use
_rseq_size directly, and reset it to 0 if rseq registration fails in
__tls_init_tp.  This function is called before relocation processing
(some architectures store IFUNC resolver information in the TCB), so
it's still okay to alter the value at this point, without running into
problems with copy relocations.

I think the simple approach would be to treat _dl_rseq_align as a global
variable, defined in one of the files listed under $(dl-routines) in
elf/Makefile (so that the definition goes into ld.so and libc.a).
Thread creation in libc doesn't need to know the alignment, it's
implicitly recorded in the static TLS allocation at that point.

> - Since RSEQ is Linux specific, should the changes in 'elf/' and
>   'sysdeps/generic/' be moved to 'sysdeps/unix/sysv/linux/'? If so, I'm
>   unsure how it would work for GLRO variables.

It should be under sysdeps/unix/sysv/linux.

Thanks,
Florian
Michael Jeanson Aug. 5, 2024, 5:52 p.m. UTC | #2
On 2024-08-03 10:41, Florian Weimer wrote:
> I don't thunk we need _dl_rseq_feature_size anymore, you can use
> _rseq_size directly, and reset it to 0 if rseq registration fails in
> __tls_init_tp.  This function is called before relocation processing
> (some architectures store IFUNC resolver information in the TCB), so
> it's still okay to alter the value at this point, without running into
> problems with copy relocations.
> 
> I think the simple approach would be to treat _dl_rseq_align as a global
> variable, defined in one of the files listed under $(dl-routines) in
> elf/Makefile (so that the definition goes into ld.so and libc.a).
> Thread creation in libc doesn't need to know the alignment, it's
> implicitly recorded in the static TLS allocation at that point.

Ack, I'll implement this and resend.

Thanks,

Michael
diff mbox series

Patch

diff --git a/elf/dl-support.c b/elf/dl-support.c
index 451932dd03..1133644491 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -131,6 +131,14 @@  int _dl_starting_up = 1;
 /* Random data provided by the kernel.  */
 void *_dl_random;
 
+/* Size of the supported rseq features.
+   Populated from the auxiliary vector with a minimum of '20'.  */
+size_t _dl_rseq_feature_size;
+
+/* Alignment requirement of the rseq area.
+   Populated from the auxiliary vector with a minimum of '32'.  */
+size_t _dl_rseq_align;
+
 /* Get architecture specific initializer.  */
 #include <dl-procruntime.c>
 #include <dl-procinfo.c>
diff --git a/elf/rtld_static_init.c b/elf/rtld_static_init.c
index e918e4ebdf..c845531601 100644
--- a/elf/rtld_static_init.c
+++ b/elf/rtld_static_init.c
@@ -78,6 +78,12 @@  __rtld_static_init (struct link_map *map)
   extern __typeof (dl->_dl_tls_static_size) _dl_tls_static_size
     attribute_hidden;
   dl->_dl_tls_static_size = _dl_tls_static_size;
+  extern __typeof (dl->_dl_rseq_feature_size) _dl_rseq_feature_size
+    attribute_hidden;
+  dl->_dl_rseq_feature_size = _dl_rseq_feature_size;
+  extern __typeof (dl->_dl_rseq_align) _dl_rseq_align
+    attribute_hidden;
+  dl->_dl_rseq_align = _dl_rseq_align;
   dl->_dl_find_object = _dl_find_object;
 
   __rtld_static_init_arch (map, dl);
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 656e8a3fa0..8f91a08952 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -610,6 +610,14 @@  struct rtld_global_ro
      See comments in elf/dl-tls.c where it is initialized.  */
   EXTERN size_t _dl_tls_static_surplus;
 
+  /* Size of the supported rseq features.
+     Populated from the auxiliary vector with a minimum of '20'.  */
+  EXTERN size_t _dl_rseq_feature_size;
+
+  /* Alignment requirement of the rseq area.
+     Populated from the auxiliary vector with a minimum of '32'.  */
+  EXTERN size_t _dl_rseq_align;
+
   /* Name of the shared object to be profiled (if any).  */
   EXTERN const char *_dl_profile;
   /* Filename of the output file.  */
diff --git a/sysdeps/unix/sysv/linux/dl-parse_auxv.h b/sysdeps/unix/sysv/linux/dl-parse_auxv.h
index ea2a58ecb1..b3ebaa80d5 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,9 @@  void _dl_parse_auxv (ElfW(auxv_t) *av, dl_parse_auxv_t auxv_values)
     GLRO(dl_sysinfo) = auxv_values[AT_SYSINFO];
 #endif
 
+  GLRO (dl_rseq_feature_size) = MAX (auxv_values[AT_RSEQ_FEATURE_SIZE],
+		  RSEQ_MIN_FEATURE_SIZE);
+  GLRO (dl_rseq_align) = MAX (auxv_values[AT_RSEQ_ALIGN], RSEQ_MIN_ALIGN);
+
   DL_PLATFORM_AUXV
 }
diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c
index a8ec2d7c18..01a39d2a74 100644
--- a/sysdeps/unix/sysv/linux/dl-sysdep.c
+++ b/sysdeps/unix/sysv/linux/dl-sysdep.c
@@ -209,6 +209,8 @@  _dl_show_auxv (void)
 	  [AT_L2_CACHEGEOMETRY - 2] =	{ "L2_CACHEGEOMETRY:  0x", hex },
 	  [AT_L3_CACHESIZE - 2] =	{ "L3_CACHESIZE:      ", dec },
 	  [AT_L3_CACHEGEOMETRY - 2] =	{ "L3_CACHEGEOMETRY:  0x", hex },
+	  [AT_RSEQ_FEATURE_SIZE - 2] =	{ "RSEQ_FEATURE_SIZE: ", dec },
+	  [AT_RSEQ_ALIGN - 2] =		{ "RSEQ_ALIGN:        ", dec },
 	};
       unsigned int idx = (unsigned int) (av->a_type - 2);
 
diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
index 7ea935b4ad..1de56329cd 100644
--- a/sysdeps/unix/sysv/linux/rseq-internal.h
+++ b/sysdeps/unix/sysv/linux/rseq-internal.h
@@ -30,6 +30,12 @@ 
 #define RSEQ_AREA_SIZE_INITIAL 32
 #define RSEQ_AREA_SIZE_INITIAL_USED 20
 
+/* Minimum feature size of the rseq area.  */
+#define RSEQ_MIN_FEATURE_SIZE 20
+
+/* Minimum alignment of the rseq area.  */
+#define RSEQ_MIN_ALIGN 32
+
 /* The variables are in .data.relro but are not yet write-protected.  */
 extern unsigned int _rseq_size attribute_hidden;
 extern ptrdiff_t _rseq_offset attribute_hidden;